先放整理流程图:
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 版权协议,转载请附上原文出处链接和本声明。