说的通俗一点,就是先发送数据,后订阅,也可以接收到数据。
这其实本是livedata 的一个特性,但是却给我们的日常使用带来了非常的不便,而且不提供API来解除粘性事件,这种做法确实不是很友好。
接下来,就带大家来揭秘一下LiveData 粘性事件的原理。
前方大量源码来袭,如有不适者,可以直接跳总结。
首先我们从发送消息开始
liveData.postValue("页面1 发送的消息")
发送消息有两个方法:setValue和postValue
setValue 只能在主线程使用,postValue可以在任何线程使用,它被调用时,通过handler切换到主线程,再调用 setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
这里有个 mVersion
要注意一下,后面会用到。然后就是通过 dispatchingValue
方法来分发消息了。
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
在这个方法里,主要是参数传的观察者是否为空,如果不为空,则向此观察者分发消息,如果为空,将会从观察者集合里面遍历观察者,进行分发。在这里,我们主要看 considerNotify
方法。
private void considerNotify(ObserverWrapper observer) {
...............
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
在我们前面提到 mVersion
用到了这里,和mLastVersion 做了比较,这点我们在下个步骤进行说明。
这就是我们全部发送消息的过程了,很简单明了,但是还不足以窥全貌,接下来我们分析另外一个步骤,监听。
liveData.observe(this) {
Log.e("TAG", "onCreate: ")
tv.setText("监听到的消息:$it")
}
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
............
owner.getLifecycle().addObserver(wrapper);
}
在这里,主要是对我们的 owner 和observer 做了一层包装,然后让 lifecycle 进行了监听。然后我们就看看 包装了点什么
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
.........
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
............
}
可以看到 LifecycleBoundObserver 继承了 ObserverWrapper ,实现了 LifecycleEventObserver 接口。
LifecycleEventObserver 接口 主要是当 lifecycle 状态改变的时候会感应到,并进行回调。
然后我们主要看看父类 ObserverWrapper :
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
............
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
}
是不是看到了一个熟悉的面孔,就是我们上个步骤 提到的 mLastVersion ,它是在这里定义的,并且默认是-1;这里会在后文进行贯穿起来,先了解它的源头。
接下来,我们先继续走流程,还是LifecycleBoundObserver 类中,当状态改变的时候,会调用 onStateChanged 方法
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
当活跃状态改变的时候,会 调用 activeStateChanged :
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
当状态是活跃状态的时候,会调用 dispatchingValue 进行数据分发,我们上文用到的分发是遍历所有观察者进行数据分发,这次是只分发当前观察者。
接下来我们进行连贯一下:
首先发送数据 postValue ,次数会让进行 mVersion++ 操作,然后遍历观察者进行分发。
然后是进行监听操作,在进行监听的时候,会使用LifecycleBoundObserver 对观察者进行包装一下,在这个操作里面,LifecycleBoundObserver 的父类 ObserverWrapper 定义了 mLastVersion 为-1 。在数据最后进行分发的时候,mLastVersion 是小于 mVersion 的,所以未拦截,然后进行了数据的分发。
然后就产生了粘性事件。
关于粘性事件的解决方案现在也有很多,这里就不做赘述 ,可以参考一下这篇文章:
https://www.jianshu.com/p/d0244c4c7cc9