一、概述
本文主要讲解LiveData的源码,结合了具体的情境,需到先理解上一篇文章Lifecycle的源码,这里默认大家使用方法都是会的,就像下面这样:
typescript
private val liveData: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
liveData.observe(this){
Log.d("MainActivity!", it)
}
liveData.value = "Hello World!"
二、添加观察者
为LiveData 添加一个观察者用到的是observe 方法,看一下这个函数的样子:
less
public abstract class LiveData<T> {
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
@MainThread
public void observe(@NonNull LifecycleOwner owner,
@NonNull Observer<? super T> observer) {
//省略一些代码
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//省略一些代码
owner.getLifecycle().addObserver(wrapper);
}
}
这里出现了一个LifecycleBoundObserver,他将我们传入的LifecycleOwner和Observer封装在里面,然后再将他添加到Lifecycle的观察者中去。
在LifecycleBoundObserver的构造函数中,调用了ObserverWrapper的构造函数:
less
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
而在ObserverWrapper中有个成员变量,将这个observer给保存了先来,接下来就会用到它。
kotlin
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
}
LiveData还将这个包装好的ObserverWrapper添加到自己的成员变量mObservers中去,这个显然就是存放 LiveData观察者的地方。
最后继续再将ObserverWrapper添加Lifecycle的观察者中去,使用这个LiveData既是一个观察者,它在观察宿主生命周期方法,又是一个被观察者,自己的数据被另一个观察者观察。
三、通知观察者
LiveData有两个设置数据的方法,也是通知观察者的方法,postValue是在非主线程中使用,而setValue是在主线程中使用。
scala
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
typescript
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
setValue()主要做了三件事情。
- 将初始值为
-1的mVersion++ - 将存储最新成员变量的
mData设置为当前的值 dispatchingValue通知观察者
先主要看dispatchingValue方法:
ini
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;
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()方法中去:
ini
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
最后看到了observer.mObserver.onChanged((T) mData)方法,调用了我们传入observer的方法,实现了消息的回调。
在这之前做了三个判断:
- 跳过非活跃观察者
验证一下各个观察者的生命周期情况。
- 动态验证
activity活跃性
我们可以看到shouldBeActive方法返回的是mOwner也就是 activity是不是至少处在STARTED生命周期。这就保证了发消息的人是活跃的,收消息的人也是活跃的。
scss
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
- 版本控制
我们在上面也强调了mVersion和mData这两个成员变量。仔细分析一下能得出一个结论:当观察者的最后版本号也就是mLastVersion在没有通过上面三个验证的时候是不会改变的,并且消息是不会发送的,就假设他前面几个消息没收到,在某一个情况下,突然上面三个验证又通过了,那他就只会保留发送的最会一次消息,也就是最新的消息,而且版本号也会被更新为最新的,中间跳过的就不要了。这到底有什么用呢,我分析完下一个特性再来讲解一下吧。
貌似LiveData的机制就这么点,其实这里面还是有很多细节在的,接下来我们逐一分析一下!
四、生命周期变化响应机制
前面我们分析了在 setvalue 的时候会触发状态改变的回调,但是他还会在另一个地方会被回调。
还记得前面包装类LifecycleBoundObserver吗?他被绑定成了 lifecycle 的观察者,在 activity 生命周期发生改变的时候就会触发它的onStateChanged回调。
less
@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方法:
ini
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
这里又走到了dispatchingValue和上面不一样的是这里传进去一个 this,上面传进去的是 null。
less
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//省略版
if (initiator != null) {
considerNotify(initiator);
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue())
}
}
}
最终还是会走到considerNotify中去。
这里回忆一下上面的版本控制,这边再模拟一种情况,当发送数据的状态是活跃的,接收消息的 activity 当前是不活跃的,无论你发了多少数据,最新的总会保留,并且在接受者 activity 状态变化时候,会重新回调considerNotify这个时候即使你先发的数据,观察者后来才活跃起来的,或者后来再加进去的,只要生命周期变化,就会收到最新的数据。这个就是粘性消息的机制。
五、dispatchingValue 强大的机制
回到上面说的dispatchingValue方法,我们把代码抄回来放在下面:
ini
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;
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;
}
这里出现了很多的mDispatchingValue和mDispatchInvalidated,理解他的关键在于你在观察者观察到数据之后又发送数据,就像这么写:刚观察到就发送消息!
javascript
liveData.observe(this){
liveData.value = "Hello World!"
}
想象一下,又好多个观察者,在他们一个个轮流收到数据的时候,中间突然有个人发送了数据,这个时候的mDispatchingValue是 True,它会将mDispatchInvalidated也变成 True,这样接下来的这一轮发送都会走在 break 中,不会触发回调。而又因为这里有个 while循环,事件分发又开始重新执行了,再继续执行给第一次没收到消息的观察者发信息的逻辑中,但这时候的发送的消息也变成最新的了,之前发送过的人就不再发送了。