一、概述
本文主要讲解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
循环,事件分发又开始重新执行了,再继续执行给第一次没收到消息的观察者发信息的逻辑中,但这时候的发送的消息也变成最新的了,之前发送过的人就不再发送了。