以前作过一篇关于Lifecycle的源码解析,里面分析了app
在一般进行使用的过程当中,咱们都是将数据经过 LiveData 进行一层包装,而后就能够进行其数据的变化监听了,那么其具体是如何实现的呢?ide
惯例,先来个简单的测试demo函数
object SplashViewModel{ var logined = MutableLiveData<Boolean>() init { logined.postValue(true) } } class SplashActivity : BaseBindingActivity<ActivitySplashBinding, SplashViewModel>() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) SplashViewModel.logined.observe(this, Observer { print(it)}) } }
只须要一个简单的 observe() 方法,就能够实现生命周期的监听,而后将数据发送到咱们的Activity中,咱们看看这个方法里面到底作了什么post
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe"); if (owner.getLifecycle().getCurrentState() == DESTROYED) { // 页面销毁,直接返回 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); }
能够看到,只是将咱们的生命周期拥有者和监听者进行了一次包装,生成了 LifecycleBoundObserver 类,而后将它添加到监听者列表中。测试
在以前的Lifecycle的源码解析文章中,咱们了解到,当页面发生变化时,会调用监听者的 onStateChanged() 方法。this
@Override boolean shouldBeActive() {//判断当前页面是否属于激活状态(便可见状态) return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { //若是页面销毁了,则直接移除当前对应的监听者 if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } //进行状态的变动 activeStateChanged(shouldBeActive()); }
因此当界面的生命周期变化时,会调用 activeStateChanged() 来进行状态的变动处理spa
//进行状态的转变 void activeStateChanged(boolean newActive) { if (newActive == mActive) { return; } mActive = newActive; boolean wasInactive = LiveData.this.mActiveCount == 0; //LiveData的激活的观察者数量进行变化 LiveData.this.mActiveCount += mActive ? 1 : -1; if (wasInactive && mActive) { //原来没有激活的观察者,如今有了新增的 // 说明LiveData从无激活的观察者->有激活的观察者 onActive();//留下钩子,给继承者使用 } if (LiveData.this.mActiveCount == 0 && !mActive) { //当前页面未激活,而且变化后,LiveData中处于激活状态的观察者数量为0, // 说明LiveData从有激活的观察者->无激活的观察者 onInactive();//留下钩子,给继承者使用 } if (mActive) {//若是页面变化为了激活状态,那么进行数据的分发 dispatchingValue(this); } } }
这里主要根据页面的激活数,预留了两个钩子函数,用户能够作一些本身的数据处理。最主要的仍是 dispatchingValue() 中的数据处理。线程
//分发数据 void dispatchingValue(@Nullable ObserverWrapper initiator) { if (mDispatchingValue) { //若是正在分发,则将mDispatchInvalidated置为true,那么在分发过程当中,会根据这个标志位从新新数据的分发 mDispatchInvalidated = true; return; } //标记正在进行数据的分发 mDispatchingValue = true; do { mDispatchInvalidated = false; if (initiator != null) {//若是有对应的监听者,直接分发给对应的监听者 considerNotify(initiator); initiator = null; } else { //遍历全部的观察者,而后进行数据的分发, // 若是分发过程当中,发现mDispatchInvalidated变化了,那么说明有新的数据变动,则退出当前混选,而后重新分发新的数据 for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); mDispatchingValue = false; } //通知某个观察者进行了数据的变化 private void considerNotify(ObserverWrapper observer) { //观察者未激活,返回 if (!observer.mActive) { return; } //观察者当前状态为激活,可是当前变为了避免可见状态,那么调用 //activeStateChanged方法 if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; } //若是数据版本已是最新的了,那么直接返回 if (observer.mLastVersion >= mVersion) { return; } //修改数据版本号 observer.mLastVersion = mVersion; //调用监听者的onChanged方法 observer.mObserver.onChanged((T) mData); }
在数据分发过程当中,根据相应的观察者数据版本号,而后和当前的数据的版本号进行比较,若是是新的数据,那么调用观察者的 onChange()方法,也就是咱们在开始时写的测试demo中的 print(it) 。code
总结一下页面发生变化时,数据的处理流程:server
那么当咱们使用 setValue() ,或者 postValue() 时,LiveData 又是作了什么处理呢?
咱们先看看 setValue()
protected void setValue(T value) { assertMainThread("setValue"); //记录当前数据的版本号 mVersion++; //记录设置的数据值 mData = value; //进行数据的分发 dispatchingValue(null); }
能够看到,直接将数据版本号+1,而后进行了数据的分发,dispatchingValue() 咱们刚才进行过度析,若是参数为null,那么会遍历全部的监听者,逐个通知全部观察者进行了数据的变化(前提是观察者处于激活状态)。
咱们再看看 postValue()
protected void postValue(T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { 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() 经过线程池技术,将数据在主线程进行了 setValue()。
1.当生命周期不可见时,会将最新的数据保存在LiveData中,而后保存相应的版本号,当其可见时,会将数据变化通知
2.当LiveData中的数据变化时,会遍历全部的监听页面,而后进行数据的变化通知。
附带一张ObserverWrapper
的结构图
本文由博客一文多发平台 OpenWrite 发布!