Android原始碼解析:LiveData
概述
簡單地來說,LiveData就是一個持有資料的類。
LiveData中的資料可以被觀察者訂閱,當資料被修改時通知觀察者。觀察者包括Fragment、Activity以及Service等。
LiveData能夠感知觀察者的生命週期。只有在觀察者處於啟用狀態(STARTED之後的狀態)才會收到資料更新;並在onDestroy時自動解註冊觀察者,避免崩潰,且減少記憶體洩露。
使用
使用LiveData子類MutableLiveData,維護一個String型別的資料:
public class MyViewModel extends ViewModel{ private MutableLiveData<String> mData; public MutableLiveData<String> getData() { if (mData == null) { mData = new MutableLiveData<>(); } return mData; } public void setData(String data){ //更新livedata中的值 mData.setValue(data); } }
接著註冊觀察者:
public class LiveDataFragment extends Activity{ private MyViewModel mViewModel; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mViewModel = ViewModelProviders.of(this).get(MyViewModel.class); mViewModel.getData().observe(this, new Observer<String>() { @Override public void onChanged(@Nullable String data) { //LiveData資料變化後的回撥 } }); } }
主要類

LiveData類圖.png
原始碼分析
從以下幾個方面對原始碼進行分析:
1. 如何註冊觀察者
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe"); if (owner.getLifecycle().getCurrentState() == DESTROYED) { // 當前Activity/Fragment為destory狀態時忽略 return; } LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); //mObservers(一個類似Map的容器)的putIfAbsent()方法用於判斷容器中的observer是否有已經和wrapper關聯, //如果已關聯則返回關聯值,否則關聯之後並返回wrapper 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; } //使用上面new的wrapper物件監聽Activity/Fragment的生命週期 owner.getLifecycle().addObserver(wrapper); }
LifecycleBoundObserver繼承自ObserverWrapper物件並實現GenericLifecycleObserver介面,當元件的生命週期發生變化後會通過onStateChanged()方法回撥過來通知ObserverWrapper生命週期變化
2. 如何監聽Activity/Fragment的生命週期
通過上面的分析,可以知道元件生命週期的觀察者就是LifecycleBoundObserver物件,下面我們看一下LifecycleBoundObserver具體實現:
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { // 判斷元件是否active return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { //元件destory後移除監聽者 removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); } }
當元件生命週期發生變化時,onStateChanged()方法會被呼叫。如果當前處於Lifecycle.State.DESTROYED時,會自動將觀察者移除;若當前處於ACTIVE狀態,則繼續執行,呼叫activeStateChanged方法,該方法在ObserverWrapper中實現
void activeStateChanged(boolean newActive) { if (newActive == mActive) { return; } //設定當前監聽的元件是否active,只有處於active狀態的元件才會通過觀察者模式通知元件資料變化 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); } }
最後呼叫的是dispatchingValue()進行資料變化時的訊息通知
void dispatchingValue(@Nullable ObserverWrapper initiator) { if (mDispatchingValue) { mDispatchInvalidated = true; return; } mDispatchingValue = true; do { mDispatchInvalidated = false; //元件生命週期變化時initiator不為空,considerNotify直接呼叫Observer的onChanged方法 if (initiator != null) { considerNotify(initiator); initiator = null; } else { //遍歷所有觀察者呼叫onChanged通知資料變化 for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); mDispatchingValue = false; }
3. setValue()或postValue()方法後,通知觀察者更新資料
LiveData提供了兩種改變資料的方法:在主執行緒呼叫的setValue()方法,以及在子執行緒中呼叫的postValue()方法。現在看下兩個方法的具體實現:
protected void setValue(T value) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); } 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() { @Override public void run() { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } //最終通過Handler在主執行緒呼叫setValue setValue((T) newValue); } }; public void postToMainThread(Runnable runnable) { if (mMainHandler == null) { synchronized (mLock) { if (mMainHandler == null) { mMainHandler = new Handler(Looper.getMainLooper()); } } } //noinspection ConstantConditions mMainHandler.post(runnable); }