1.前言
LiveData是Android Jetpack中的重要组件,也是我们实现MVVM架构的一种方式。它提供了一种可观察的数据,让开发者能通过观测LiveData获取数据的变动。在LiveData中我们最常用的方法是,setValue和postValue,所以我打算已这两个函数为入口对LiveData进行探究。本文是看了 LiveData为何这么香,这些你都知道吗?之后写的。
2.setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
@MainThread这个注释表示setValue()需要在主线程中调用,函数内又使用assertMainThread断言来确保方法是运行在主线程的。mVersion这个属性表示了是用于对值 的新旧进行比较,后续还会用到。然后就是mData = value对值就行保存。接下来就进入了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;
}
这段代码中有两个标志属性:mDispatchingValue,mDispatchInvalidated,这两个是用来判断当前这个值分发是否在进行,要是没有这两个属性,就有可能会导致新的值被旧的值覆盖。mDispatchingValue = true的时候表示值分发正在进行,如果传入的initiator(观察者)是空的话,就通知所有的观察者。如果在分发过程中有新的值传入的话mDispatchInvalidated就会为true,当前的for循环就会跳出,导致从头开始分发新的值。以上都是本人各人理解。(PS.我有一点不懂的是如果新方法进入的时候mDispatchInvalidated = true运行完之后刚刚好之前的函数运行到mDispatchInvalidated = false怎么办)。这个方法中通知各个观察者的方法是considerNotify,我们继续来看它的源码。
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);
}
这个方法我们先大体看一下,大概就是判断这个观察者是否是活跃状态,新更新的这个值是否比当前的值新(通过version比较),如果以上条件都满足就通知给观察者。这个方法里面有一个shouldBeActive的调用也很有意思,我们也可以看看它的源码。ctrl+左键点击发现这个函数是一个抽象函数,我们可以使用ctrl+alt+b点击ObserverWrapper这个抽象类就能看见它的实现类。分别是AlwaysActiveObserver和LifecycleBoundObserver,我们先开比较简单的AlwaysActiveObserver,这个类目就能看出它的作用。
private class AlwaysActiveObserver extends ObserverWrapper {
@Override
boolean shouldBeActive() {
return true;
}
}
就是这个观察者会一直活跃。另一个LifecycleBoundObserver,顾名思义肯定是跟生命周期有关系,
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
}
public enum State {
DESTROYED,
INITIALIZED,
CREATED,
STARTED,
RESUMED;
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
}
根据源码可以知道这个观测者只会在状态为STARTED和RESUMED的时候进行观察,这也让我们知道LiveData是如何自动绑定生命周期的。setValue的流程基本就到这里了,如果有什么缺漏或者错误,希望大家多多指出。
3.postValue
postValue没有对调用线程进行限制,所以所有线程中都可以调用postValue
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) { //mPendingData!=NOT_SET
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
多次调用postValue方法时,只有最后一次会生效,因为当postValue的任务正在进行时,mPendingData!=NOT_SET,这样就不会post新的任务,只有上一次post结束时,才会开始下一次,而此时mPendingData等于最后一次更新的值。再接下去就是调用setValue了,就是重复上面的过程。
4.小结
这算是第一次比较认真的去读官方的源码,我觉得官方源码的命名都特别规范,很多都能见名知意。确实很不错,我觉得这一部分代码中设计最好的就是dispatchingValue这一部分,通过两个标志位防止覆盖。要是让我来写,可能会复杂很多。