LiveData源码分析

  • Post author:
  • Post category:其他


先放整理流程图:

1.postValue调2次只触发1次?

postValue本质是把新值保存到LiveData的mPendingData成员变量里,版本号+1,把执行Runnable post到主线程,在主线程setValue。

多次调用会更新mPendingData的值,但Runnable已经post过了就不再post了。

2.粘性事件是怎么回事

参考文章开始的流程图,下面几种情况导致考虑调用回调(considerNotify):

  • setValue
  • postValue(最终调setValue)
  • 当生命周期状态变化时(observer通过装饰模式,被赋予了生命周期状态监听的能力)

considerNotify时:

  • 如果LifecycleOwner至少是START状态,则认为是活跃的
  • 如果observer的mLastVersion(默认为-1)大于新事件的版本号,则忽略

对于粘性事件,初始时设置了值,但是因为没有监听端,在setValue -> considerNotify时,值无法被消费,新注册了observer后,值才被消费。

3.可以在observer被回调时setValue?

可以。

分析见文章开始的流程图。

dispatchingValue方法虽然是单线程模型,但是做了对《在回调中setValue》的防护。

详细源码如下:

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // 如果当前正在for循环中回调结果,则标记为“分发已刷新”状态,不再分发
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                // 如果处于“分发已刷新”状态,说明值改变了,需要break并重新执行do-while语句
                // 重新对所有observer进行结果回调
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}



版权声明:本文为starry_eve原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。