前提
- LiveDataのonActive/onInactiveで処理を行わせていた
- 強制的にLiveDataをactiveにするため、次のようなExtensionを作った
- LiveDataをactiveにしたいだけなので
- Observerはナニも処理していない
fun <T> LiveData<T>.forceActiveAlive(owner: LifecycleOwner) {
observeForever(Observer { })
}
問題点
- 2箇所以上から
LiveData.forceActiveAlive()
を呼び出す
- 1箇所でもonDestroyが走ると、LiveDataがinactiveになる
理由
- Kotlinのコンパイラが、
Observer { /* drop value. */ }
をシングルトンとして最適化し、コンパイルしていた
- 気持ちとしては、ここは常に新しいインスタンスを作ってほしかった
- コンパイル後の実態は中身はstaticメソッドで処理も無いのため、Kotlinコンパイラの気持ちもわかる
- そのため、2回め以降の
LiveData.forceActiveAlive()
で実行がキャンセルされていた
解法
private class ObserverWrapper<T>(private val observer: Observer<T>) : Observer<T> {
override fun onChanged(t: T?) {
observer.onChanged(t)
}
}
fun <T> LiveData<T>.forceActiveAlive(owner: LifecycleOwner) {
observeForever(ObserverWrapper(Observer { }))
}
コンパイラの気持ちをわかってあげよう
- コンパイラの気持ちを考えれば、このバグは回避できたかもしれないんだ