eaglesakuraの技術ブログ

技術的な話題とか、メモとか。

LiveDataを複数回observeしても1個のObserverしか登録されない現象と解法

前提

  • LiveDataのonActive/onInactiveで処理を行わせていた
  • 強制的にLiveDataをactiveにするため、次のようなExtensionを作った
    • LiveDataをactiveにしたいだけなので
    • Observerはナニも処理していない
// 強制的にLiveDataをactiveにする
fun <T> LiveData<T>.forceActiveAlive(owner: LifecycleOwner) {
    observeForever(Observer { /* drop value. */ })
}

問題点

  • 2箇所以上から LiveData.forceActiveAlive() を呼び出す
  • 1箇所でもonDestroyが走ると、LiveDataがinactiveになる

理由

  • Kotlinのコンパイラが、 Observer { /* drop value. */ } をシングルトンとして最適化し、コンパイルしていた
  • そのため、2回め以降の LiveData.forceActiveAlive() で実行がキャンセルされていた

解法

  • 毎度newが走るようにしてあげれば想定通りに動く
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 { /* drop value. */ }))
}

コンパイラの気持ちをわかってあげよう

  • コンパイラの気持ちを考えれば、このバグは回避できたかもしれないんだ