Android源碼進階之LiveData工作原理詳解
本文轉(zhuǎn)載自微信公眾號「Android開發(fā)編程」,作者Android開發(fā)編程。轉(zhuǎn)載本文請聯(lián)系Android開發(fā)編程公眾號。
前言
LiveData 是一種可觀察的數(shù)據(jù)存儲器類。與常規(guī)的可觀察類不同,LiveData 具有生命周期感知能力,意指它遵循其他應用組件(如 Activity、Fragment 或 Service)的生命周期。
這種感知能力可確保 LiveData 僅更新處于活躍生命周期狀態(tài)的應用組件觀察者。
LiveData本身是觀察者,觀察組件的Lifecycle,也是被觀察者,數(shù)據(jù)變化時要通知數(shù)據(jù)的觀察者。
前面我們講解了Lifecycle實現(xiàn)原理,今天我們來看LiveData
源碼進階之lifecycle組件原理分析
一、livedata的在app中的應用
1、使用livedata的步驟
- 創(chuàng)建一個實例LiveData來保存某種類型的數(shù)據(jù)。這通常在你的ViewModel類內(nèi)完成;
 - 創(chuàng)建一個Observer 定義onChanged()方法的對象,該對象 控制LiveData對象保存的數(shù)據(jù)更改時發(fā)生的情況。您通常Observer在UI控制器中創(chuàng)建對象,例如activity或fragment;
 - 使用該 方法將Observer對象附加到對象。該方法需要一個對象。這將對象訂閱到對象,以便通知其更改。您通常將該對象附加到UI控制器中,例如活動或片段;
 
2、livedata的簡單例子
在viewModel中之定義live data
- public class NameViewModel extends ViewModel {
 - // Create a LiveData with a String
 - private MutableLiveData<String> mCurrentName;
 - public MutableLiveData<String> getCurrentName() {
 - if (mCurrentName == null) {
 - mCurrentName = new MutableLiveData<String>();
 - }
 - return mCurrentName;
 - }
 - // Rest of the ViewModel...
 - }
 
在activity或者Fragment中實施監(jiān)聽來更新ui
- public class NameActivity extends AppCompatActivity {
 - private NameViewModel mModel;
 - @Override
 - protected void onCreate(Bundle savedInstanceState) {
 - super.onCreate(savedInstanceState);
 - // Other code to setup the activity...
 - // Get the ViewModel.
 - mModel = ViewModelProviders.of(this).get(NameViewModel.class);
 - // Create the observer which updates the UI.
 - final Observer<String> nameObserver = new Observer<String>() {
 - @Override
 - public void onChanged(@Nullable final String newName) {
 - // Update the UI, in this case, a TextView.
 - mNameTextView.setText(newName);
 - //注意這里 在MVVM 中不是這樣寫的 這里只是單行綁定
 - }
 - };
 - // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
 - mModel.getCurrentName().observe(this, nameObserver);
 - //注意這個地方用沒有用Java8的lambda表達式,可以寫的更加簡練,
 - }
 - }
 
更新livedata對象
調(diào)用setValue(T)示例會導致觀察者onChanged()使用該值調(diào)用其ui進行刷新。該示例示出了按鈕按下,但setValue()還是postValue()可以被調(diào)用以更新mName為各種各樣的原因,包括響應于網(wǎng)絡請求或數(shù)據(jù)庫負荷完成; 在所有情況下,呼叫setValue()或postValue()觸發(fā)觀察員并更新UI;
- mButton.setOnClickListener(new OnClickListener() {
 - @Override
 - public void onClick(View v) {
 - String anotherName = "John Doe";
 - mModel.getCurrentName().setValue(anotherName);
 - }
 - });
 - mButton.setOnClickListener(new OnClickListener() {
 - @Override
 - public void onClick(View v) {
 - String anotherName = "John Doe";
 - mModel.getCurrentName().setValue(anotherName);
 - }
 - });
 
二、livedata原理詳細分析
1、observe 方法
- 首先這個方法只能在主線程注冊觀察;
 - 官方文檔說LiveData僅處于活躍生命周期才有效,所以一開始就開始判斷是否為 Lifecycle.Stete.DESTROYED,是的話就沒有然后了,直接return;
 - 接下來就是 創(chuàng)建 LifecycleBoundObserver ,生命周期變化邏輯在這里面;
 - 然后就是最后一行注冊觀察,如果想了解 Lifecycle.addObserver 做了什么可以看 Android Lifecycle實現(xiàn)原理;
 
- //map 的 key 為LiveData數(shù)據(jù)觀察者,value為組件的Lifecycle觀察者
 - private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
 - new SafeIterableMap<>();
 - @MainThread
 - public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
 - assertMainThread("observe");
 - //判斷當前生命周期的狀態(tài)
 - if (owner.getLifecycle().getCurrentState() == DESTROYED) {
 - // ignore
 - return;
 - }
 - //Lifecycle的生命周期變化邏輯在這里
 - LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
 - //mObservers 保存
 - 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;
 - }
 - //感知lifecycle的生命周期變化
 - owner.getLifecycle().addObserver(wrapper);
 - }
 
2、LifecycleBoundObserver
- LifecycleBoundObserver 繼承 ObserverWrapper ,實現(xiàn) LifecycleEventObserver 接口。
 - ObserverWrapper 用于判斷組件當前是否活躍;
 - LifecycleEventObserver 就是 Lifecycle 的觀察者了,重寫了 onStateChanged 方法,當Lifecycle 生命周期發(fā)生變化時,就會在此方法接收到,LiveData 也就能感知到,如果組件的生命周期是 DESTROYED ,那也就移除觀察;
 - 到這里 LiveData 對組件的生命周期感知就注冊完成了,可以開始發(fā)送數(shù)據(jù);
 
- class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
 - @NonNull
 - //一般組件,比如Activity、fragment可以會實現(xiàn)LifecycleOwner ,可以拿到lifecycle
 - final LifecycleOwner mOwner;
 - LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
 - super(observer);
 - mOwner = owner;
 - }
 - /* 判斷當前組件當前是否活躍 */
 - @Override
 - boolean shouldBeActive() {
 - return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
 - }
 - @Override
 - public void onStateChanged(@NonNull LifecycleOwner source,
 - @NonNull Lifecycle.Event event) {
 - //獲取當前生命周期狀態(tài)
 - Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
 - //如果組件已銷毀了,就移除觀察
 - if (currentState == DESTROYED) {
 - removeObserver(mObserver);
 - return;
 - }
 - Lifecycle.State prevState = null;
 - while (prevState != currentState) {
 - prevState = currentState;
 - activeStateChanged(shouldBeActive());
 - currentState = mOwner.getLifecycle().getCurrentState();
 - }
 - }
 - /* 判斷是否綁定 */
 - @Override
 - boolean isAttachedTo(LifecycleOwner owner) {
 - return mOwner == owner;
 - }
 - /* 移除觀察 */
 - @Override
 - void detachObserver() {
 - mOwner.getLifecycle().removeObserver(this);
 - }
 - }
 
3、activeStateChanged
ObserverWrapper 這個類里面有個方法,后面的粘性事件會用到;
- void activeStateChanged(boolean newActive) {
 - //組件狀態(tài)如果不變返回
 - if (newActive == mActive) {
 - return;
 - }
 - // immediately set active state, so we'd never dispatch anything to inactive
 - // owner
 - mActive = newActive;
 - changeActiveCounter(mActive ? 1 : -1);
 - //如果是活動的就發(fā)送數(shù)據(jù)
 - if (mActive) {
 - dispatchingValue(this);
 - }
 - }
 
4、發(fā)送數(shù)據(jù)分析
4.1、postValue 發(fā)送數(shù)據(jù)到主線程
這個方法最核心的就是利用主線程Handler發(fā)送數(shù)據(jù),一步步拆開分析;
- protected void postValue(T value) {
 - boolean postTask;
 - //加鎖
 - synchronized (mDataLock) {
 - postTask = mPendingData == NOT_SET;
 - //保存要發(fā)送的數(shù)據(jù)value
 - mPendingData = value;
 - }
 - if (!postTask) {
 - return;
 - }
 - //利用主線程Handler發(fā)送
 - ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
 - }
 
4.2、postValue 其實就是 setValue
在postValue 要發(fā)送的 Runnable ,可以看到最后一行就是 setValue 方法,數(shù)據(jù)也即是之前保存的mPendingData ,只是在這又給 newValue;
- private final Runnable mPostValueRunnable = new Runnable() {
 - @SuppressWarnings("unchecked")
 - @Override
 - public void run() {
 - Object newValue;
 - synchronized (mDataLock) {
 - newValue = mPendingData;
 - mPendingData = NOT_SET;
 - }
 - setValue((T) newValue);
 - }
 - };
 
4.3、postToMainThread 主線程Handler
ArchTaskExecutor 類 postToMainThread 方法,實際就是 DefaultTaskExecutor 類執(zhí)行 postToMainThread 方法;
- public class ArchTaskExecutor extends TaskExecutor {
 - @NonNull
 - private TaskExecutor mDelegate;
 - @NonNull
 - private TaskExecutor mDefaultTaskExecutor;
 - private ArchTaskExecutor() {
 - mDefaultTaskExecutor = new DefaultTaskExecutor();
 - mDelegate = mDefaultTaskExecutor;
 - }
 - ...
 - @Override
 - public void postToMainThread(Runnable runnable) {
 - mDelegate.postToMainThread(runnable);
 - }
 - ...
 - }
 
4.4、DefaultTaskExecutor類
我們知道是 DefaultTaskExecutor. postToMainThread,就直接看這個方法,哎呀,太熟悉的代碼,創(chuàng)建 Handler ,傳入的是 Looper.getMainLooper() ,就是主線程Handler ,然后就 post 消息;
- public class DefaultTaskExecutor extends TaskExecutor {
 - @Nullable
 - private volatile Handler mMainHandler;
 - @Override
 - public void postToMainThread(Runnable runnable) {
 - if (mMainHandler == null) {
 - synchronized (mLock) {
 - if (mMainHandler == null) {
 - mMainHandler = createAsync(Looper.getMainLooper());
 - }
 - }
 - }
 - //noinspection ConstantConditions
 - mMainHandler.post(runnable);
 - }
 - }
 
4.5、setValue 方法
mVersion 在初始化的構(gòu)造方法里就賦值了,為-1,每次setValue,版本號就會變一次;
setValue 也就是用 mData 保存一下 value ,然后交給 dispatchingValue 方法處理;
- @MainThread
 - protected void setValue(T value) {
 - assertMainThread("setValue");
 - mVersion++;
 - mData = value;
 - dispatchingValue(null);
 - }
 
4.6、dispatchingValue 方法
setValue走該方法,傳的 initiator為空,那就遍歷 mObservers 保存的觀察者發(fā)送數(shù)據(jù);
- @SuppressWarnings("WeakerAccess") /* synthetic access */
 - void dispatchingValue(@Nullable ObserverWrapper initiator) {
 - if (mDispatchingValue) {
 - mDispatchInvalidated = true;
 - return;
 - }
 - mDispatchingValue = true;
 - do {
 - mDispatchInvalidated = false;
 - if (initiator != null) {
 - //粘性事件,就單個觀察者接受數(shù)據(jù)
 - considerNotify(initiator);
 - initiator = null;
 - } else {
 - //setvalue 傳過來 initiator 為空,執(zhí)行這里
 - // mObservers 拿出來,逐個發(fā)送數(shù)據(jù)
 - for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
 - mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
 - considerNotify(iterator.next().getValue());
 - if (mDispatchInvalidated) {
 - break;
 - }
 - }
 - }
 - } while (mDispatchInvalidated);
 - mDispatchingValue = false;
 - }
 
4.7、considerNotify 判斷發(fā)送數(shù)據(jù)
- 這里先判斷組件是否活動
 - 在判斷粘性事件
 - 然后用 mVersion ,判斷是否發(fā)送過數(shù)據(jù)
 - 最后才是給觀察者發(fā)送數(shù)據(jù)
 
- 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;
 - }
 - //校驗是否發(fā)送過數(shù)據(jù)
 - if (observer.mLastVersion >= mVersion) {
 - return;
 - }
 - observer.mLastVersion = mVersion;
 - //發(fā)送數(shù)據(jù)
 - observer.mObserver.onChanged((T) mData);
 - }
 
5、粘性事件分析
- 粘性事件就是先發(fā)送數(shù)據(jù),后面再注冊觀察者,還能收到消息;
 - 我們就從LiveData.observe 開始,新的頁面注冊LiveData觀察者,也注冊Lifecycle觀察;
 - 當新頁面生命周期變化,就會執(zhí)行 LifecycleBoundObserver.onStateChanged 的方法;
 - 接下來 activeStateChanged 方法,因為是新頁面,組件狀態(tài)是活動的,就走到 dispatchingValue 方法;
 - dispatchingValue 傳進來當前新頁面的 initiator 是不為空的,就只會給當前觀察者發(fā)送數(shù)據(jù);
 
總結(jié):
1、LifecycleOwner生命周期從非活躍變成活躍狀態(tài)時:
Livedata添加一個觀察者時,會關聯(lián)一個LifecycleOwner,然后把這個觀察者包裝成一個LifecycleBoundObserver,和LifecycleOwner的getLifecycle關聯(lián),當LifecycleBoundObserver的生命周期變化時,會調(diào)用LifecycleBoundObserver的onStateChanged方法,在這個方法中判斷當前生命周期和上次的生命周期是否是同一類型(要么活躍要么非活躍),如果是,就直接返回,避免重復通知(start通知了,resume就不需要通知了),如果不是同一類型,并且當前生命周期是活躍狀態(tài),就調(diào)用dispatchingValue方法通知觀察者,判斷LifecycleOwner是否時活躍狀態(tài),如果是,將Livedata中持有的最新更新給觀察者;
2、Livedata中的值改變時:
同樣是調(diào)用dispatchingValue,判斷LifecycleOwner是否時活躍狀態(tài),如果是,就遍歷通知所有觀察者;


















 
 
 

 
 
 
 