LiveDataのpostValueは全て流れてくるとは限らない

結論

背景

RxJavaのSubjectの代替としてMutableLiveData(postValueとsetValueがpublicになっている)を使っている部分があり、短い間に2回コールされたとき、全ての値が流れて欲しかったが何故か1回しか叩かれていなかった。 どこに原因があるか調査したところ、どうもpostValueメソッドの仕様(LiveDataクラス全体の仕様?)的に短い間に複数回コールされた場合は、最後にpostValueした値のみをpostするようになっていた。

実装詳細

LiveDataのpostValueのコードは以下のようになっています(v1.0.0)

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

postValueメソッドでは

    1. mPendingDataフィールドにObserverに渡すデータをセットする
  1. メインスレッドでmPostValueRunnableを実行する (ただしmPendingDataにまだ以前のデータが残っていたら、以前のデータを更新する)

といったことをやっています。

このコードを見て分かる通り、前にセットしたmPendingDataがObserverに渡される前に、新しい値で上書きされる可能性があることが分かります。 よって、短い間に複数回のpostValueをコールすると最後の値のみしかObserverに流れてこない可能性があります。

まとめ

Written by
あんどろいどでぃべろっぱぁー🍎