Jetpack入坑(二)LiveData源碼分析理解

LiveData是一個可觀察的數據存儲器。它可以通過觀察者Observer與LifecycleOwner配對來感知數據依附組件的生命週期狀態,只會把更新通知發給活躍的觀察者,所謂活躍就是觀察者處於STARTED或者RESUMED狀態而沒有DESTROYED。

既然是數組存儲器,他是如何更新數據呢

 LiveData有postValue()和setValue()方法去更新數據。postValue(T value)可以在任意線程使用,setValue(T value)只能在主線程更新數據。

postValue(T value)源碼:

 protected void postValue(T value) {
        //定義一個boolean值
        boolean postTask;
        //可以在任意線程  所以要加鎖
        synchronized (mDataLock) {
            //NOT_SET全局的一個空對象 mPendingData初始值就是NOT_SET   從此處代碼的理解我們       
            //要結合下面mPostValueRunnable去理解  每一次主線程更新數據之後重新初始                                    
            //mPendingData的值 postTask纔會爲true 纔可以下一次更新
            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;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

通過postValue(T value)源碼我們可以知道他只是在多線程調用時候加了個鎖,然後最終還是通過setValue(T value)去分發數據。 

setValue(T value)源碼:

 @MainThread
    protected void setValue(T value) {
        //先判斷當前線程是否爲主線程,是的話數據版本+1 然後dispatching數據  是不是想到了view的 
        //事件分發- -
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
   //爲什麼setValue中該方法參數會傳null,這要從該方法調用的兩種情況說起
   //一個情況就是setValue 那就傳一個null  去把數據更新到所有活躍的觀察者
   //另一個情況就是某一個觀察者由不活躍狀態到活躍狀態 更新該觀察者對應的被觀察者
   //知道了這兩種情況  這裏的代碼就好理解了
 @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                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;
        }
        // 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
        observer.mObserver.onChanged((T) mData);
    }

通過setValue(T value)的源碼,我們看到LiveData在更新數據時會遍歷所有註冊的觀察者,只有活躍的觀察者纔可以通知UI更新。

那LiveData又是如何感知觀察者的活躍狀態呢

首先我們來看LiveData的使用示例代碼:

 viewModel.getData().observe(this,object :Observer<List<String>> {//非lamda更直觀
            override fun onChanged(t: List<String>?) {
               //TODO 更新UI
            }

        })

通過observe方法的操作:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //主線程判斷
        assertMainThread("observe");
        //生命週期狀態判斷  銷燬了就別費事了
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //observer和Liferecycle完美結合  LifecycleBoundObserver實現了LifecycleObserver
        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);
    }
    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() {
            //是否是Started以及之上的狀態  
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //組件Lifecycle生命週期狀態變化調用該方法  組件銷燬就移除該觀察者 組件起死回生就更新數 
        //據
        @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);
        }
    }
        
       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) {
                //成功和setValue源碼匯合
                dispatchingValue(this);
            }
        }

源碼看完誇兩句,LiveData的優勢:

確保界面符合數據狀態

LiveData 遵循觀察者模式。當生命週期狀態發生變化時,LiveData 會通知 Observer 對象。您可以整合代碼以在這些 Observer 對象中更新界面。觀察者可以在每次發生更改時更新界面,而不是在每次應用數據發生更改時更新界面。

不會發生內存泄露

泄漏?不存在的,這輩子都不可能泄漏的!

不會因 Activity 停止而導致崩潰

如果觀察者的生命週期處於非活躍狀態(如返回棧中的 Activity),則它不會接收任何 LiveData 事件。(異步數據頁面關閉的View空指針)

不再需要手動處理生命週期

界面組件只是觀察相關數據,不會停止或恢復觀察。LiveData 將自動管理所有這些操作,因爲它在觀察時可以感知相關的生命週期狀態變化。

數據始終保持最新狀態

如果生命週期變爲非活躍狀態,它會在再次變爲活躍狀態時接收最新的數據。例如,曾經在後臺的 Activity 會在返回前臺後立即接收最新的數據。

適當的配置更改

再也不用擔心橫豎屏組件重新裝件去保存數據了。

共享資源

您可以使用單一實例模式擴展 LiveData 對象以封裝系統服務,以便在應用中共享它們。LiveData 對象連接到系統服務一次,然後需要相應資源的任何觀察者只需觀察 LiveData 對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章