【AAC 系列三】深入理解架构组件,androidjetpack 视频
}//ObserverWrapper.activeStateChangedactiveStateChanged(shouldBeActive());}
@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}
@Overridevoid detachObserver() {mOwner.getLifecycle().removeObserver(this);}}
**ObserverWrapper?**:
private abstract class ObserverWrapper {final Observer<T> mObserver;boolean mActive;int mLastVersion = START_VERSION;
ObserverWrapper(Observer<T> observer) {mObserver = observer;}//是否是 active 状态 abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {return false;}
void detachObserver() {}
void activeStateChanged(boolean newActive) {if (newActive == mActive) {return;}// immediately set active state, so we'd never dispatch anything to inactive// ownermActive = newActive;boolean wasInactive = LiveData.this.mActiveCount == 0;LiveData.this.mActiveCount += mActive ? 1 : -1;if (wasInactive && mActive) {onActive();}if (LiveData.this.mActiveCount == 0 && !mActive) {onInactive();}//如果 active 状态下,则发送数据更新通知 if (mActive) {dispatchingValue(this);}}}
仔细看下这两个类其实就能解答疑问了。
LifecycleBoundObserver 是 抽象类?ObserverWrapper 的子类,重写了?shouldBeActive() 方法,在 owner 处于至少是 STARTED 的状态下认为是 active 状态;并且它也实现了 GenericLifecycleObserver 接口,可以监听 lifecycle 回调,并且在?onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定,并且将下个流程交给了 activeStateChanged() 。
到这里?【2.1】、【2.3】的问题已经有了答案:
【2.1】答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包装了 observer ,并且通过它绑定了 owner。
【2.3】答:LifecycleBoundObserver 在?onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定。
这里需要注意的是,当我们调用 observe() 注册后,由于绑定了 owner,所以在 active 的情况下,LiveData 如果有数据,则 Observer 会立马接受到该数据修改的通知。
此时的流程是:
observe-->
onStateChanged-->
activeStateChanged-->
dispat
chingValue-->
considerNotify-->
onChanged
可以称之为生命周期改变触发的流程,另外还有一种流程是 postValue&setValue 触发的流程,共两种。
2.3?activeStateChanged(boolean)
在 activeStateChanged() 方法里,处理了?onActive() 跟?onInactive() 回调的相关逻辑处理,并且调用了 dispatchingValue(this) 。(MediatorLiveData 用到了 onActive() 跟 onInactive() 有兴趣自行了解,这里不展开)
接下去探索 dispatchingValue
。
2.4?dispatchingValue(ObserverWrapper) 分析
private void dispatchingValue(@Nullable ObserverWrapper initiator) {//如果正在分发则直接返回 if (mDispatchingValue) {//标记分发失效 mDispatchInvalidated = true;return;}//标记分发开始 mDispatchingValue = true;do {mDispatchInvalidated = false;//生命周期改变调用的方法 initiator 不为 nullif (initiator != null) {considerNotify(initiator);initiator = null;} else {//postValue/setValue 方法调用 传递的 initiator 为 nullfor (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);//标记分发结束 mDispatchingValue = false;}
considerNotify(ObserverWrapper)
? 方法:
private void considerNotify(ObserverWrapper observer) {//检查状态 确保不会分发给 inactive 的 observerif (!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;}//setValue 会增加 version ,初始 version 为-1if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//noinspection uncheckedobserver.mObserver.onChanged((T) mData);}
可以看到?dispatchingValue 正是分发事件逻辑的处理方法,而 considerNotify 方法则确保了只将最新的数据分发给 active 状态下的 Observer?。
另外也可以看到 LiveData 引入了版本管理来管理数据 (mData)以确保发送的数据总是最新的。(具体不多讲)
dispatchingValue?这里分两种情况:
ObserverWrapper 不为 null
ObserverWrapper 为 null
需要着重讲一下。
2.4.1 ObserverWrapper 不为 null 的情况
上面提到过,LifecycleBoundObserver.onStateChanged 方法里调用了?activeStateChanged ,而该方法调用 dispatchingValue(this);传入了 this ,也就是?LifecycleBoundObserver ,这时候不为 null 。
也就是说生命周期改变触发的流程就是这种情况,这种情况下,只会通知跟该 Owner 绑定的 Observer。
2.4.2?ObserverWrapper 为 null 的情况
上面我也提前说了,除了生命周期改变触发的流程外,还有 postValue&setValue 流程,来看下这俩方法。
private final Runnable mPostValueRunnable = new Runnable() {@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}//noinspection unchecked//调用 setValuesetValue((T) newValue);}};
protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}
@MainThreadprotected void setValue(T value) {//必须在主线程调用 否则会 crashassertMainThread("setValue");mVersion++;//增加版本号 mData = value;//传入了 nulldispatchingValue(null);}
LiveData 的?postValue 方法其实就是把操作 post 到主线程,最后调用的还是 setValue 方法,注意 setValue 必须是在主线程调用。
并且可以看到** setValue 方法调用了 dispatchingValue 方法,并传入了 null ,这个时候的流程则会通知 active 的 mObservers**。
到这里之前的剩下的所有疑问也都可以解答了。
LiveData 的两个流程都会走到?dispatchingValue 处理分发通知逻辑,并且在分发通知前会判断 owner 的状态,再加上 LiveData 本身内部的版本管理,确保了只会发送最新的数据给 active 状态下的 Observer。
**注意:**LiveData 对同时多次修改数据做了处理,如果同时多次修改,只会修改为最新的数据。
3. 图解 LiveData
3.1 LiveData 类图
再看一遍类图,回顾一下:
3.2 LiveData 流程图
Lifecycle 改变触发流程:
(图 3.Lifecycle 改变触发流程图)
Lifecycle postValue/setValue 触发流程:
(图 4.setValue 改变触发流程图)
4. LiveData tips and recipes
LiveData 还有很多其他相关知识,这里列举一些,更多实践可以看一下【7.6】。
4.1 Sticky Event
LiveData 被订阅时,如果之前已经更改过数据,并且当前 owner 为 active 的状态,activeStateChanged() 会被调用,也即会立马通知到 Observer ,这样其实就类似 EventBus 的 sticky event 的功能,需要注意的是,很多时候我们并不需要该功能。具体可以看一下【7.6】的处理。
4.2 AlwaysActiveObserver
默认情况下,LiveData 会跟 LicycleOwner 绑定,只在 active 状态下更新,如若想要不管在什么状态下都能接收到数据的更改通知的话,怎么办?这时候需要使用 AlwaysActiveObserver ,改调用 observe 方法为调用 LiveData.observeForever(Observer) 方法即可。
4.3?MediatorLiveData
LiveData 还有一个子类是?MediatorLiveData,它允许我们合并多个 LiveData,任何一个 LiveData 有更新就会发送通知。比如我们的数据来源有两个,一个数据库一个网络,这时候我们会有两个 DataSource,也就是两个 LiveData,这个时候我们可以使用 MediatorLiveData 来 merge 这两个 LiveData。
4.4?Transformations
Transformations 允许我们把一个 LiveData 进行处理,变化成另外一个 LiveData,目前支持 map 跟 switchMap 两个方法,跟 RxJava 的操作类似。
比如,用 map 把一个 String 类型的 LiveData 转换成 Integer 类型:
Transformations.map(liveString, new Function<String, Integer>() {@Overridepublic Integer apply(final String input) {return Integer.valueOf(input);
评论