以前作過一篇關於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 發佈!