Android Jetpack 之 LiveData - 3

這是我參與更文挑戰的第22天,活動詳情查看: 更文挑戰java

源碼分析

LiveData#observe

private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();

	@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            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);
    }

複製代碼

咱們調用observer()時,傳遞了兩個參數,第一個是LifecycleOwner接口實例,而咱們繼承的AppCompatActivity的父類就已經實現了這個接口,因此咱們傳this便可;第二個參數Observer就是咱們觀察的回調。android

先判斷是否是主線程,不是就拋異常,而後經過 owner.getLifecycle().getCurrentState() 獲取狀態,判斷是否已經被銷燬,若是已經被銷燬,直接返回(由於已經說過只對處於活躍狀態的組件作更新);git

接着將owner和observer構形成LifecycleBoundObserver實例,這是一個內部類,裏面有關於狀態變換的一系列操做,待會詳細分析;github

而後將observer和wrapper存入map緩存中,若是observer緩存已存在而且已經和另外一個LifecycleOwner綁定,則拋出異常;若是緩存已經存在則直接忽略;緩存

即一個 Observer 實例,只能綁定一個 LifecycleOwner,而一個 owner 能夠綁定多個 Observer 實例;markdown

最後調用addObserver方法將LifecycleBoundObserver實例和LifecycleOwner綁定。而addObserver是調用了LifecycleRegistry類的實現。app

當 owner (Activity 或者 fragment) 生命週期變化的時候,會回調 LifecycleBoundObserver 的 onStateChanged 方法,onStateChanged 方法又會回調 observer 的 onChange 方法。異步

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() {
            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);
        }
    }
複製代碼
private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        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;
            // 激活狀態的 observer 個數從 0 到 1
            if (wasInactive && mActive) {
                onActive();// 空實現,通常讓子類去重寫
            }
            // 激活狀態的 observer 個數從 1 到 0
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();// 空實現,通常讓子類去重寫
            }
            // 激活狀態,向觀察者發送 LiveData 的值
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }
複製代碼

咱們來看一下 LifecycleBoundObserver,繼承 ObserverWrapper,實現了 GenericLifecycleObserver 接口。而 GenericLifecycleObserver 接口又實現了 LifecycleObserver 接口。它包裝了咱們外部的 observer,有點相似於代理模式。咱們能夠回顧下Lifecycle組件相關的內容。當組件(Fragment、Activity)生命週期變化時會經過onStateChanged()方法回調過來。ide

GenericLifecycleObserver#onStateChangedoop

Activity 回調週期變化的時候,會回調 onStateChanged ,會先判斷 mOwner.getLifecycle().getCurrentState() 是否已經 destroy 了,若是。已經 destroy,直接移除觀察者。這也就是爲何咱們不須要手動 remove observer 的緣由

若是不是銷燬狀態,會調用 activeStateChanged 方法 ,攜帶的參數爲 shouldBeActive() 返回的值。 而當 lifecycle 的 state 爲 STARTED 或者 RESUMED 的時候,shouldBeActive 方法的返回值爲 true,即表示激活。

activeStateChanged 方法中,,當 newActive 爲 true,而且不等於上一次的值,會增長 LiveData 的 mActiveCount 計數。接着能夠看到,onActive 會在 mActiveCount 爲 1 時觸發,onInactive 方法則只會在 mActiveCount 爲 0 時觸發。即回調 onActive 方法的時候活躍的 observer 剛好爲 1,回調 onInactive 方法的時候,沒有一個 Observer 處於激活狀態。

當 mActive 爲 true 時,會促發 dispatchingValue 方法。

@SuppressWarnings("WeakerAccess") /* synthetic access */
    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<? super 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,進行分發

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);
    }
複製代碼
  1. 若是狀態不是在活躍中,直接返回,這也就是爲何當咱們的 Activity 處於 onPause, onStop, onDestroy 的時候,不會回調 observer 的 onChange 方法的緣由。
  2. 判斷數據是不是最新,若是是最新,返回,不處理
  3. 數據不是最新,回調 mObserver.onChanged 方法。並將 mData 傳遞過去

LiveData#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 方法一次。

LiveData#postValue

protected void postValue(T value) {
        boolean postTask;
    	// 鎖住
        synchronized (mDataLock) {
             // 當前沒有人在處理 post 任務
            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
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };
複製代碼
  1. 首先,採用同步機制,經過 postTask = mPendingData == NOT_SET 有沒有人在處理任務。 true,沒人在處理任務, false ,有人在處理任務,有人在處理任務的話,直接返回
  2. 調用 AppToolkitTaskExecutor.getInstance().postToMainThread 到主線程執行 mPostValueRunnable 任務。

LiveData#observeForever

@MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        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);
    }
複製代碼

由於 AlwaysActiveObserver 沒有實現 GenericLifecycleObserver 方法接口,因此在 Activity o生命週期變化的時候,不會回調 onStateChange 方法。從而也不會主動 remove 掉 observer。由於咱們的 obsever 被 remove 掉是依賴於 Activity 生命週期變化的時候,回調 GenericLifecycleObserver 的 onStateChange 方法。

時序圖

借用網上的一張圖

image.png

LiveData主要涉及到的時序有三個:

  • 在Fragment/Activity中經過LiveData.observer()添加觀察者(observer()方法中的第二個參數)。
  • 根據Fragment/Activity生命週期發生變化時,移除觀察者或者通知觀察者更新數據。
  • 當調用LiveData的setValue()、postValue()方法後,通知觀察者更新數據。

todo

NetworkBoundResource

juejin.cn/post/684490…

權限

juejin.cn/post/5c106a…

總結

LiveData優勢

1. 確保UI符合數據狀態 LiveData遵循觀察者模式。 當生命週期狀態改變時,LiveData會向Observer發出通知。 您能夠把更新UI的代碼合併在這些Observer對象中。沒必要去考慮致使數據變化的各個時機,每次數據有變化,Observer都會去更新UI。

2. 沒有內存泄漏 Observer會綁定具備生命週期的對象,並在這個綁定的對象被銷燬後自行清理。

3. 不會因中止Activity而發生崩潰 若是Observer的生命週期處於非活躍狀態,例如在後退堆棧中的Activity,就不會收到任何LiveData事件的通知。

4.不須要手動處理生命週期 UI組件只須要去觀察相關數據,不須要手動去中止或恢復觀察。LiveData會進行自動管理這些事情,由於在觀察時,它會感知到相應組件的生命週期變化。

5. 始終保持最新的數據 若是一個對象的生命週期變到非活躍狀態,它將在再次變爲活躍狀態時接收最新的數據。 例如,後臺Activity在返回到前臺後當即收到最新數據。

6. 正確應對配置更改 若是一個Activity或Fragment因爲配置更改(如設備旋轉)而從新建立,它會當即收到最新的可用數據。

7.共享資源 您可使用單例模式擴展LiveData對象幷包裝成系統服務,以便在應用程序中進行共享。LiveData對象一旦鏈接到系統服務,任何須要該資源的Observer都只需觀察這個LiveData對象。

使用 LiveData 對象步驟

  • LiveData基於觀察者模式實現,而且和LifecycleOwner進行綁定,而LifecycleOwner又被Fragment和Activity實現,因此它能夠感知生命週期;在當前的LifecycleOwner不處於活動狀態(例如onPasue()onStop())時,LiveData是不會回調observe()的,由於沒有意義.
  • 同時LiveData只會在LifecycleOwner處於Active的狀態下通知數據改變,果數據改變發生在非 active 狀態,數據會變化,可是不發送通知,等 owner 回到 active 的狀態下,再發送通知;
  • LiveData在DESTROYED時會移除Observer,取消訂閱,不會出現內存泄漏
  • postValue在異步線程,setValue在主線程
  • 若是LiveData沒有被observe(),那麼此時你調用這個LiveData的postValue(...)/value=...,是沒有任何做用

參考

官方文檔:LiveData 概覽

Jetpack源碼解析—LiveData的使用及工做原理

Android livedata 源碼解剖

Android源碼解析-LiveData

相關文章
相關標籤/搜索