Google Architecture之LiveData、ViewModel源碼分析

一、我們想象中的生命周期感應應該是怎樣的?

1、設想

監聽過程如果讓我們開始自己去實現一個簡單的生命周期感應框架,剛開始很可能是這樣的。


first_glance.png

自己實現一個Data<T>,里面有一個集合,保存所有的Observer。同時BaseActivity包含一個Data的集合,當生命周期變化的時候去動態注銷UI和Data的訂閱關系。

2、google的實現

google_implement.png

google把生命周期處理邏輯抽離到一個單獨的LifecycleRegistry中,并將數據的邏輯放在LiveData中,職責更加清晰明了。
在多線程處理,LiveData狀態的保持,以及事件的變化傳遞控制更加細致具體。

二、Observer監聽過程以及生命周期感應

1、監聽過程

(1·1)LiveData.observe()

  • 將Observer對象添加到LiveData中(后續Data變化,聲明周期變化通知Observer)
    //LiveData::observe()
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //(裝飾者模式)封裝成一個能一個能接收并處理生命周期事件的LifecycleBoundObserver類,
        //LifecycleBoundObserver會當FragmentActivity/Fragment的onDestroy()調用之后將所有的監聽關系移除掉
        //LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //將observer作為key添加到Map中(注意:同一個liveData能被多個observer監聽)
        //注意防止重復監聽導致邏輯可能出錯,例如重復執行網絡請求的時候很容易多次發生多次監聽
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //同一個Observer對象不能綁定多個不同擁有生命周期的對象
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //參見2
        owner.getLifecycle().addObserver(wrapper);
    }

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);
        }
    }

(1·2)owner.getLifecycle().addObserver(wrapper);

  • 將Observer對象添加到Lifecycle中(Lifecycle能接收FragmentActivity/Fragment生命周期變化)
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        //將Observer添加到mObserverMap中,此處被封裝成一個ObserverWithState類(具有狀態屬性)
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        
        if (previous != null) {
            return;
        }
        //省略observer與LifecycleRegistry狀態同步邏輯(后面有分析).....
    }

ObserverWithState類

    //
    //ObserverWithState::dispatchEvent()
    //接收生命周期事件,并進行狀態的變更,同時將事件傳遞給GenericLifecycleObserver處理
    //(其實也就是上面第一步的LifecycleBoundObserver),方便進行監聽關系的注銷
    void dispatchEvent(LifecycleOwner owner, Event event) {
            //計算接收Event事件之后應該處于哪種狀態
            State newState = getStateAfter(event);
            mState = min(mState, newState);//此句多余
            mLifecycleObserver.onStateChanged(owner, event);
            //更新并記錄新狀態
            mState = newState;
        }

2、生命周期的感應

(2·1)生命周期的捕獲

記得在步驟(1·1)中需要傳入一個實現了LifecycleOwner接口的對象。而我們一般傳入的是FragmentActivity/Fragment,此時我們直接點開FragmentActivity源碼之后一層層剝掉其外殼,將會發現它的父類SupportActivity其實實現了LifecycleOwner接口,并且會通過接口的getLifecycle()方法返回一個Lifecycle的子類(也就是LifecycleRegstry)。

SupportActivity這個類代碼并不多,大致看一下就能明白其意思

重點: 你會發現這行代碼

protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在FragmentActivity上面添加一個無界面的Fragment(利用Fragment生命周期和Activity/Fragment綁定在一起的特點,
        //實現hook到Activity/Fragment的生命周期事件,將其整合到一起處理,達到低耦合高內聚的目的)。有興趣的可以去分
        //析glide的動態取消加載圖片請求邏輯,甚至可以自己開發一個動態取消網絡請求的網絡庫開源項目。
        ReportFragment.injectIfNeededIn(this);
    }

在ReportFragment的各個生命周期回調方法中會調用dispatch(Lifecycle.Event event)方法,將生命周期事件傳遞給前面提到過的Lifecycle的子類(也就是LifecycleRegstry)。

private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        //LifecycleRegistryOwner目前已標記棄用,可不管
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }
        
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                //將事件傳遞給LifecycleRegstry對象
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

分析到這里我們大致總結一下:(同時可以加入一些猜想和自己的理解)

現在FragmentActivity/Fragment的生命周期事件會通過ReportFragment傳遞給LifecycleRegistry。
然后我們大膽猜想下,在LifecycleRegistry在處理事件的時候是否當收到on_destroy事件的時候就通過前面步驟(1·2)中的ObserverWithState類通知Observer,然后進行Observer的監聽注銷呢?

帶著疑問和猜想,我們繼續去分析LifecycleRegistry中的邏輯。

(2·2)LifecycleRegistry生命周期事件的處理以及狀態變化

在講這部分邏輯之前,需要將里面涉及到的幾個重要的狀態變化方法邏輯圖理一遍。

其實這部分狀態機的變化圖你也可以不用花這么大精力去理解,因為我們真正關心的只有on_destroy事件,只有收到它我們才會去注銷監聽關系。所以本部分邏輯你可以不需要深入理解。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        //接收生命周期事件,計算得出應該處于什么狀態,參照邏輯圖理解
        State next = getStateAfter(event);
        moveToState(next);
    }
private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        //保存接收事件后的狀態
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        //根據當前的狀態mState,去更新Map中Observer的狀態
        //mHandlingEvent在addObserver(@NonNull LifecycleObserver observer)方法會用到
        //用來判斷協同是否有正在進行相同的sync邏輯,避免重復執行
        mHandlingEvent = true;
        //根據當前的狀態mState,去更新Map中Observer的狀態
        sync();
        mHandlingEvent = false;
    }

moveToState() -----> sync()

//同步所有的Observer與LifecycleResitry的狀態(也就是Activity/Fragment的狀態)
private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
                    + "new events from it.");
            return;
        }
        //isSynced()會判斷當前map中頭尾的Observer狀態與LifecycleRegistry中mState一致
        //不一致表示在sync同步狀態過程中有新的Observer加入map中了
        while (!isSynced()) {
            mNewEventOccurred = false;
            //Activity/Fragment狀態從被銷毀或啟動其它界面時,與其綁定的Observer狀態的同步
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
            //Activity/Fragment啟動時,與其綁定的Observer狀態的同步
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

moveToState() -----> backwardPass()
或者
moveToState() -----> forwardPass()

    //Activity/Fragment啟動時,與其綁定的Observer狀態的同步
    //注意: 多個Observer監聽同一個LiveData,并且Observer 中有相同的邏輯處理,
    //最終的處理結果以最后添加的Observer中的邏輯為準。
    private void forwardPass(LifecycleOwner lifecycleOwner) {
        //mObserverMap從Start到End進行遍歷(最早添加-->最近添加,越早越靠前)。
        //這里的ascendingIterator就是上面現象的原因,具體翻閱源碼分析下
        Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                //while state in observer.mState到mState,逐次計算出觸發狀態變化的事件,傳遞給
                //ObserverWithState處理
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
    }
    //Activity/Fragment狀態從被銷毀或啟動其它界面時,與其綁定的Observer狀態的同步
    private void backwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));
                //將生命周期shijian傳遞給ObserverWithState
                observer.dispatchEvent(lifecycleOwner, event);
                popParentState();
            }
        }
    }

ObserverWithState

ObserverWithState是LifecycleRegistry的內部類

static class ObserverWithState {
        State mState;
        GenericLifecycleObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            mLifecycleObserver = Lifecycling.getCallback(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            //改變ObserverWithState狀態,同時將生命周期Event傳遞給LifecycleBoundObserver
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

LifecycleBoundObserver

LifecycleBoundObserver是LiveData的內部類

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
            super(observer);
            mOwner = owner;
        }

        //狀態為Started或Resumed才處于激活狀態
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //注意:如果Observer綁定的Activity/Fragment處于DESTROYED(onDestroy方法調用之后)狀態,就將所有的觀察訂閱關系注銷
            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);
        }
    }

LiveData:

    @MainThread
    public void removeObserver(@NonNull final Observer<T> observer) {
        assertMainThread("removeObserver");
        //移除LiveData中的Observer
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        //調用LifecycleBoundObserver的detachObserver()方法
        //也就是移除LifecycleRegistry中的Observer引用
        removed.detachObserver();
        //更改observer的狀態
        removed.activeStateChanged(false);
    }

(2·3)關鍵方法狀態變化邏輯圖

回顧下Activity的生命周期:

activity_lifecycle.png

LifecycleRegistry的狀態轉換圖:

google_lifecycle.png

LifecycleRegistry的狀態轉換關鍵控制方法:

key_function.png

3、Observer狀態與Registry的同步

LifecycleRegistry的方法sync()只在兩個地方調用到了:

  1. LifecycleRegistry::addObserver(@NonNull LifecycleObserver observer)
  2. LifecycleRegistry::moveToState(State next)
@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        
        ......
        
        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
private void moveToState(State next) {
        
        ......
        
        //根據當前的狀態mState,去更新Map中Observer的狀態
        //mHandlingEvent在addObserver(@NonNull LifecycleObserver observer)方法會用到
        //用來判斷協同是否有正在進行相同的sync邏輯,避免重復執行
        mHandlingEvent = true;
        //根據當前的狀態mState,去更新Map中Observer的狀態
        sync();
        mHandlingEvent = false;
    }

因為涉及到多線程操作(如addObserver可能在其他線程執行)。這里的總體邏輯就是如果當前只要有一個地方在執行sync操作,另一個都無須再次執行sync方法進行同步。
這和sync方法的邏輯有關

while(!isSynced()){
    ...
}

isSynced方法就是判斷當前LifecycleRegistry狀態mState是否和Map中的首位的Observer狀態是否一致(因為每次添加新的Observer都會觸發sync,所以每次只要判斷首尾Observer就行)。

意思就是只要首尾不一致,就肯定不同步。
首尾一致,因為同步是遍歷的,那么肯定同步。

private boolean isSynced() {
        if (mObserverMap.size() == 0) {
            return true;
        }
        State eldestObserverState = mObserverMap.eldest().getValue().mState;
        State newestObserverState = mObserverMap.newest().getValue().mState;
        return eldestObserverState == newestObserverState && mState == newestObserverState;
    }

4、ViewModel的生命周期管理

這部分相對簡單很多。邏輯主要在FragmentActivity的以下三個方法中

  1. onCreate()
  2. onRetainNonConfigurationInstance()
  3. onDestroy()
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ...
    // 恢復mViewModelStore
    FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
    if (nc != null && nc.viewModelStore != null && this.mViewModelStore == null) {
        this.mViewModelStore = nc.viewModelStore;
    }
        
    ...
}
protected void onDestroy() {
        super.onDestroy();
        //Configurations發生變化而引起的onDestroy不會銷毀ViewModel
        if (this.mViewModelStore != null && !this.isChangingConfigurations()) {
            this.mViewModelStore.clear();
        }

        this.mFragments.dispatchDestroy();
    }
//mViewModelStore的持久化
public final Object onRetainNonConfigurationInstance() {
        Object custom = this.onRetainCustomNonConfigurationInstance();
        FragmentManagerNonConfig fragments = this.mFragments.retainNestedNonConfig();
        if (fragments == null && this.mViewModelStore == null && custom == null) {
            return null;
        } else {
            FragmentActivity.NonConfigurationInstances nci = new FragmentActivity.NonConfigurationInstances();
            nci.custom = custom;
            nci.viewModelStore = this.mViewModelStore;
            nci.fragments = fragments;
            return nci;
        }
    }

5、總結

  1. 不同Observe監聽相同LiveData,生命周期沒控制好,導致崩潰
  2. 多個不同Observer監聽同一個LiveData,并且Observer 中有相同的邏輯處理,最終的處理結果以最后添加的Observer中的邏輯為準。
  3. 默認的Observer的只會在Activity或Fragment處于onStarted/onResumed狀態下才會接收到LiveData的數據;或者重新處于onStarted/onResumed時。

6、思考

  1. 如何在不同的Activity之間共享ViewModel?
    答:自己去實現一個ViewModelStore,自己控制它的生命周期。
  2. ViewModel是否幫我們做了數據持久化?
    答:ViewModel沒做數據的持久化,只是內存變量的復用。
  3. 怎樣讓observer處于onCreated狀態也能處理數據?
    答:目前并沒有提供對應API去自定義Observer的邏輯觸發時機。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容