和普通的观察者模式相比,LiveData具有生命周期感应的能力,这样就可以在适当的时候向观察者分发数据而不需要用户手动处理回调,通常我们只需要在onCreate方法中调用下面方法就万事大吉。
LiveData.java
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);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
下图简单的说明了此方法完成的工作,observer是来观察LiveData数据的,wrapper是观察沈明周期时间的
image.png
LifecycleBoundObserver 实现了GenericLifecycleObserver接口,可以作为生命周期观察者添加到LifecycleRegistry中,也就可以收到生命周期事件的分发,即所谓的生命周期感应能力。具体过程参考LifecycleRegistry添加观察者的介绍
LifecycleBoundObserver .java
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
当走完上面的observe方法,我们会立马收到LifecycleOwner分发的事件,如果LifecycleOwner进入DESTROYED状态,LiveData就会进行清理操作,
- 从LiveData的链表中移除观察者记录
- 从LifecycleRegistry中移除ObserverWrapper
- 更新状态为非活跃,活跃的观察者就会减少一个
LiveData.java
public void removeObserver(@NonNull final Observer<? super T> observer) {
assertMainThread("removeObserver");
//从LiveData的链表中移除观察者记录
ObserverWrapper removed = mObservers.remove(observer);
if (removed == null) {
return;
}
//从LifecycleRegistry中移除ObserverWrapper
removed.detachObserver();
//更新状态为非活跃
removed.activeStateChanged(false);
}
如果状态不是DESTROYED,执行activeStateChanged,当前状态是否活跃由shouldBeActive()方法决定,判断很简单就是当前状态至少是STARTED
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
如果正常启动,我们的状态依此为CREATED、STARTED、RESUMED ,CREATED状态下newActive = mActive=false,直接返回;RESUMED状态下newActive = mActive=true,直接返回不会重复分发;STARTED状态下才会正常分发
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
//LiveData可能有多个观察者,记录活跃的数量
LiveData.this.mActiveCount += mActive ? 1 : -1;
//LiveData有了第一个活跃的观察者
if (wasInactive && mActive) {
onActive();
}
//LiveData失去了最后一个活跃的观察者
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
//只有在活跃状态才向此观察者分发数据
if (mActive) {
dispatchingValue(this);
}
}
分发分为两种,一种是只针对当前的ObserverWrapper 分发,另外一种是对LiveData记录的所有观察者分发,我们现在是第一种:就是一个新的观察者添加到LiveData中,只要LifecycleOwner的状态是活跃的,观察者就会收到最新的数据
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方法,首先是再次判断观察者的状态,然后判断observer的数据的版本和LiveData中的数据版本,只有当LiveData的数据比observer的新才有必要更新,如果LiveData的数据从来没有设置过,新加的观察者不会收到更新通知
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;
//noinspection unchecked
//我们UI中的观察者在此被调用通知
observer.mObserver.onChanged((T) mData);
}
在主线程使用setValue更新LiveData的数值,首先更新版本号,然后更新数据再分发,这里的dispatchingValue参数为null就是第二种分发。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
在子线程更新涉及到postValue方法和mPostValueRunnable,在子线程中不会直接更新mData,而是先更新mPendingData ,
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
//可能有多个子线程更新,如果主线程没有更新,mPendingData!=null,就不再post了,
//防止多次向主线程发出更新请求,导致观察者所得到的值都不是最新的
postTask = mPendingData == NOT_SET;
//可能被子线程多次更新,只有最新的值被主线程更新
mPendingData = value;
}
//如果主线程没有更新最新值不要继续请求
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
//使用子线程更新的值,并重置mPendingData ,表示更新了
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
总的来说,LiveData像一个中间商,他自己内部维护一个链表,用来防止Observer的无效或重复添加,并在数据更新时能遍历通知Observer,它自己并没有感知生命周期的能力,是把Observer封装成LifecycleBoundObserver添加到LifecycleRegistry中去获取、记录状态并根据Observer的状态和数据的版本来分发数据,当LifeCycleOwner进入DESTROYED状态,又能移除所有关系。
同一个LifeCycleOwner下关系图
网友评论