Android livedata 原始碼解剖
說在前面
本次推出 Android Architecture Components 系列文章,目前寫好了四篇,主要是關於 lifecycle,livedata 的使用和原始碼分析,其餘的 Navigation, Paging library,Room,WorkMannager 等春節結束之後會更新,歡迎關注我的公眾號,有更新的話會第一時間會在公眾號上面通知。
github sample 地址: ArchiteComponentsSample
Android 技術人,一位不羈的碼農。

Android 技術人
前言
在前面三篇部落格中,我們已經介紹了 lifecycle 的使用及原理,livedata ,ViewModel 的常用用法,今天,讓我們一起來學習 livedata 的原理。
我們先來回顧一下 LiveData 的特點:
LiveData 是一個可以被觀察的資料持有類,它可以感知 Activity、Fragment或Service 等元件的生命週期。
- 它可以做到在元件處於啟用狀態的時候才會回撥相應的方法,從而重新整理相應的 UI。
- 不用擔心發生記憶體洩漏
- 當 config 導致 activity 重新建立的時候,不需要手動取處理資料的儲存和恢復。內部已經幫我們封裝好了。
- 當 Actiivty 不是處於啟用狀態的時候,如果你想 livedata setValue 之後立即回撥 obsever 的 onChange 方法,而不是等到 Activity 處於啟用狀態的時候才回調 obsever 的 onChange 方法,你可以使用 observeForever 方法,但是你必須在 onDestroy 的時候 removeObserver
下面,讓我們一步步解剖它
原理分析
我們知道 livedata 的使用很簡單,它是採用觀察者模式實現的
- 新增觀察者
- 在資料改變的時候設定 value,這樣會回撥 Observer 的 onChanged 方法
MutableLiveData<String> nameEvent = mTestViewModel.getNameEvent(); nameEvent.observe(this, new Observer<String>() { @Override public void onChanged(@Nullable String s) { Log.i(TAG, "onChanged: s = " + s); mTvName.setText(s); } });
observe 方法
@MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { // 判斷是否已經銷燬 if (owner.getLifecycle().getCurrentState() == DESTROYED) { // ignore return; } LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); // observer 已經新增過了,並且快取的 observer 跟 owner 的 observer 不一致,狀態異常,丟擲異常 if (existing != null && !existing.isAttachedTo(owner)) { throw new IllegalArgumentException("Cannot add the same observer" + " with different lifecycles"); } // 已經新增過 Observer 了,返回回去 if (existing != null) { return; } // 新增 observer owner.getLifecycle().addObserver(wrapper); }
首先,我們先來看一下它的 observe 方法,首先通過 owner.getLifecycle().getCurrentState() 獲取狀態,判斷是否已經被銷燬,如果已經被銷燬,直接返回。接著用 LifecycleBoundObserver 包裝起來。然後從快取的 mObservers 中讀取 observer,如果有,證明已經新增過了。
observe 方法,小結起來就是
- 判斷是否已經銷燬,如果銷燬,直接移除
- 用 LifecycleBoundObserver 包裝傳遞進來的 observer
- 是否已經新增過,新增過,直接返回
- 將包裝後的 LifecycleBoundObserver 新增進去
因此,當 owner 你(Activity 或者 fragment) 生命週期變化的時候,會回撥 LifecycleBoundObserver 的 onStateChanged 方法,onStateChanged 方法又會回撥 observer 的 onChange 方法
LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); } }
我們來看一下 LifecycleBoundObserver,繼承 ObserverWrapper,實現了 GenericLifecycleObserver 介面。而 GenericLifecycleObserver 介面又實現了 LifecycleObserver 介面。 它包裝了我們外部的 observer,有點類似於代理模式。
GenericLifecycleObserver#onStateChanged
Activity 回撥週期變化的時候,會回撥 onStateChanged ,會先判斷 mOwner.getLifecycle().getCurrentState() 是否已經 destroy 了,如果。已經 destroy,直接移除觀察者。 這也就是為什麼我們不需要手動 remove observer 的原因 。
如果不是銷燬狀態,會呼叫 activeStateChanged 方法 ,攜帶的引數為 shouldBeActive() 返回的值。
而當 lifecycle 的 state 為 started 或者 resume 的時候,shouldBeActive 方法的返回值為 true,即表示啟用。
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.this.mActiveCount += mActive ? 1 : -1; if (wasInactive && mActive) { onActive(); } if (LiveData.this.mActiveCount == 0 && !mActive) { onInactive(); } if (mActive) { dispatchingValue(this); }
}
activeStateChanged 方法中,,當 newActive 為 true,並且不等於上一次的值,會增加 LiveData 的 mActiveCount 計數。接著可以看到,onActive 會在 mActiveCount 為 1 時觸發,onInactive 方法則只會在 mActiveCount 為 0 時觸發。 即回撥 onActive 方法的時候活躍的 observer 恰好為 1,回撥 onInactive 方法的時候,沒有一個 Observer 處於啟用狀態。
當 mActive 為 true 時,會促發 dispatchingValue 方法。
dispatchingValue
private void dispatchingValue(@Nullable ObserverWrapper initiator) { // 如果正在處理,直接返回 if (mDispatchingValue) { mDispatchInvalidated = true; return; } mDispatchingValue = true; do { mDispatchInvalidated = false; // initiator 不為 null,呼叫 considerNotify 方法 if (initiator != null) { considerNotify(initiator); initiator = null; } else { // 為 null 的時候,遍歷所有的 obsever,進行分發 for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); // 分發完成,設定為 false mDispatchingValue = false; }
其中 mDispatchingValue, mDispatchInvalidated 只在 dispatchingValue 方法中使用,顯然這兩個變數是為了防止重複分發相同的內容。當 initiator 不為 null,只處理當前 observer,為 null 的時候,遍歷所有的 obsever,進行分發
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; //noinspection unchecked // 呼叫外部的 mObserver 的 onChange 方法 observer.mObserver.onChanged((T) mData); }
- 如果狀態不是在活躍中,直接返回,這也就是為什麼當我們的 Activity 處於 onPause, onStop, onDestroy 的時候,不會回撥 observer 的 onChange 方法的原因。
- 判斷資料是否是最新,如果是最新,返回,不處理
- 資料不是最新,回撥 mObserver.onChanged 方法。並將 mData 傳遞過去
setValue
@MainThread protected void setValue(T value) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); }
setValue 方法中,首先,斷言是主執行緒,接著 mVersion + 1; 並將 value 賦值給 mData,接著呼叫 dispatchingValue 方法。dispatchingValue 傳遞 null,代表處理所有 的 observer。
這個時候如果我們依附的 activity 處於 onPause 或者 onStop 的時候,雖然在 dispatchingValue 方法中直接返回,不會呼叫 observer 的 onChange 方法。但是當所依附的 activity 重新回到前臺的時候,會促發 LifecycleBoundObserver onStateChange 方法,onStateChange 又會呼叫 dispatchingValue 方法,在該方法中,因為 mLastVersion < mVersion。所以會回撥 obsever 的 onChange 方法,這也就是 LiveData 設計得比較巧妙的一個地方
同理,當 activity 處於後臺的時候,您多次呼叫 livedata 的 setValue 方法,最終只會回撥 livedata observer 的 onChange 方法一次。
postValue
protected void postValue(T value) { boolean postTask; // 鎖住 synchronized (mDataLock) { // 當前沒有人在處理 post 任務 postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return; } AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); } private final Runnable mPostValueRunnable = new Runnable() { @Override public void run() { Object newValue; synchronized (mDataLock) { newValue = mPendingData; // 處理完畢之後將 mPendingData 置為 NOT_SET mPendingData = NOT_SET; } //noinspection unchecked setValue((T) newValue); } };
- 首先,採用同步機制,通過 postTask = mPendingData == NOT_SET 有沒有人在處理任務。 true,沒人在處理任務, false ,有人在處理任務,有人在處理任務的話,直接返回
- 呼叫 AppToolkitTaskExecutor.getInstance().postToMainThread 到主執行緒執行 mPostValueRunnable 任務。
@MainThread public void observeForever(@NonNull Observer<T> observer) { AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer); ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) { throw new IllegalArgumentException("Cannot add the same observer" + " with different lifecycles"); } if (existing != null) { return; } wrapper.activeStateChanged(true); } private class AlwaysActiveObserver extends ObserverWrapper { AlwaysActiveObserver(Observer<T> observer) { super(observer); } @Override boolean shouldBeActive() { return true; } }
因為 AlwaysActiveObserver 沒有實現 GenericLifecycleObserver 方法介面,所以在 Activity o生命週期變化的時候,不會回撥 onStateChange 方法。從而也不會主動 remove 掉 observer。因為我們的 obsever 被 remove 掉是依賴於 Activity 生命週期變化的時候,回撥 GenericLifecycleObserver 的 onStateChange 方法。
總結
- liveData 當我們 addObserver 的時候,會用 LifecycleBoundObserver 包裝 observer,而 LifecycleBoundObserver 可以感應生命週期,當 activity 生命週期變化的時候,如果不是處於啟用狀態,判斷是否需要 remove 生命週期,需要 remove,不需要,直接返回
- 當處於啟用狀態的時候,會判斷是不是 mVersion最新版本,不是的話需要將上一次快取的資料通知相應的 observer,並將 mLastVsersion 置為最新
- 當我們呼叫 setValue 的時候,mVersion +1,如果處於啟用狀態,直接處理,如果不是處理啟用狀態,返回,等到下次處於啟用狀態的時候,在進行相應的處理
- 如果你想 livedata setValue 之後立即回撥資料,而不是等到生命週期變化的時候才回調資料,你可以使用 observeForever 方法,但是你必須在 onDestroy 的時候 removeObserver。因為 AlwaysActiveObserver 沒有實現 GenericLifecycleObserver 介面,不能感應生命週期。

image
題外話
Android Architecture Components 已經寫了四篇文章了,其餘的 Navigation, Paging library,Room,WorkMannager 等春節結束之後再更新了,歡迎關注我的公眾號,有更新的話會第一時間在公眾好上面更新。