0%

LiveData

一般来说,这种观察者模式都是先订阅,后收到消息。但是 LiveData 有粘性效果,就是我先改变数据,后订阅,但是还能收到之前修改(只保存一个,就是最后那个数据的粘性)的数据。

LiveData 就是利用 Lifecycle ,它的 Observer 是 如果发现状态是 DESTROY 状态,就会 remove 掉这个 Observer 观察者,所以我们在代码种都是 MyLiveData.info1.observe(this, MyObserver()) 添加 Observer ,但是并没有反注册移除 Observer 的操作,就是因为在 DESTROY 的时候,它自己会移除。首先来看 LiveData 的使用:

1
2
3
4
5
6
7
8
9
10
11
object MyLiveData { // 单例
// 懒加载
val info1: MutableLiveData<String> by lazy { MutableLiveData() }
}


MyLiveData.info1.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {

}
})

我们可以定义一个 MutableLiveData ,然后去 observe 它,当上面的 info1 有改变时,下面的 onChanged() 方法就会调用。看下 observe 的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//必须要再主线程
assertMainThread("observe");
//如果当前Lifecycle 已经到了 DESTROYED 状态了,就不理会
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}

//将传入的 observer 包装成 LifecycleObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//observer 缓存到 Map 种
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}

//包装的 Observer 添加到 Lifecycle 中
owner.getLifecycle().addObserver(wrapper);
}

首先,observe 操作必须在主线程调用,否则会报错。其次,会将传入的 observer 保存在 Map 中,最后,将封装的 LifecycleObserver 添加到 Lifecycle 的监听中去。到这里貌似没有可以继续分析的代码了,我们来看值的改变,因为值的改变会触发传入的 observer ,有 postValue 和 setValue 两种方法:

1
2
MyLiveData.info1.value = "初始化"
MyLiveData.info1.postValue("开始啦")

其实, postValue 最终也是使用 setValue 实现的:

1
2
3
4
5
6
7
8
9
10
11
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

首先经过线程同步,最后将操作 post 到主线程操作。这个 runnable 就是调用 setValue 的操作:

1
2
3
4
5
6
7
8
9
10
11
12
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};

所以,我们可以猜测,setValue 应该是要在主线程调用的,使用 postValue 也是为了在子线程中调用能够 setValue

1
2
3
4
5
6
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}

从代码可以看出,setValue 确实需要在主线程调用,并且,每次调用之后,就会 mVersion ++ ,在 setValue 之后,可以看到调用了 dispatchingValue 将这个 value 值分发给观察者了:

1
2
3
4
5
6
7
8
9
10
11
void dispatchingValue (@Nullable ObserverWrapper initiator) {
//省略其他代码
for (Iterator< Map.Entry < Observer < ? super T >, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
//省略其他代码
}

省略了其他代码,可以看到,不断从 mObservers 中(Map 类型,就是前面 observe 的时候,将 Observer 保存到的那个 Map)取出元素去做 considerNotify 操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}

所以,LiveData 中有很多 Active 的判断,其中下面的判断:

1
2
3
if (observer.mLastVersion >= mVersion) {
return;
}

这个地方决定了消息的粘性,也就是通过版本号来决定粘性,其实判断的就是是 setValue/postValue 和 observe 的先后关系,如果我们通过反射让他们的值相等,即: observer.mLastVersion == mVersion ,这样就会执行里面的 return ,if 后面的语句将不会执行,也就不会有粘性了(在订阅行为发生以前的改动都不会发送过来)。

另外,我们看到,当生命周期状态改变时,就会调用 onStateChanged :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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();
}
}

从这里可以知道,当 状态变为 DESTROYED 的时候,就会执行 removeObserver(mObserver); 移除 Observer 的操作,所以,我们才不需要手动去 remove 。

谢谢你的鼓励