Android Jetpack架構組件(五)帶你瞭解LiveData(原理篇)


本文首發於微信公衆號「後廠技術官」

前言

在上一篇文章中我們學習了LiveData的基本用法,我們知道LiveData是一個可觀察的數據持有者,他是具有組件生命週期感知的,那麼它是如何觀察組件生命週期變化的呢?LiveData和RxJava的不同的是,LiveData並不是通知所有觀察者,它只會通知處於Active狀態的觀察者,如果一個觀察者處於DESTROYED狀態,它將不會收到通知,這一點又是如何做到的?還有另外一點,Transformations的map方法其內部進行了什麼操作?等等問題,會在這篇文章中給大家進行講解。

1.LiveData如何觀察組件生命週期變化

通過調用LiveData的observe方法來註冊觀察者,LiveData的observe方法如下所示。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

 @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        //如果被觀察者的當前的狀態是DESTROYED,就return
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {//1
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//2
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);//3
        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);//4
    }

註釋1處的owner實際上就是註冊時傳進來來組件,比如Activity,獲取組件當前的狀態,如果狀態爲DESTROYED,那麼直接return,這說明DESTROYED狀態的組件是不允許註冊的。

如果你還不瞭解Lifecycle的狀態,可以查看Android Jetpack架構組件(三)帶你瞭解Lifecycle(原理篇)這篇文章。
註釋2處新建了一個LifecycleBoundObserver包裝類,將owner和observer傳了進去。
註釋3處將observer和LifecycleBoundObserver存儲到SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers中,putIfAbsent方法和put方法有區別,如果傳入key對應的value已經存在,就返回存在的value,不進行替換。如果不存在,就添加key和value,返回null。
如果等於null,在註釋4處會將LifecycleBoundObserver添加到Lifecycle中完成註冊,這樣當我們調用LiveData的observe方法時,實際上是LiveData內部完成了Lifecycle的觀察者的添加,這樣LiveData自然也就有了觀察組件生命週期變化的能力。

2.LiveData的observe方法回調

LifecycleBoundObservers是LiveData的內部類,代碼如下所示。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

 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);//1
                return;
            }
            activeStateChanged(shouldBeActive());//2
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
        

LifecycleBoundObserver繼承了ObserverWrapper類,重寫了shouldBeActive方法,用於判斷當前傳入的組件的狀態是否是Active的,Active狀態包括STARTED和RESUMED狀態。

LifecycleBoundObserver實現了GenericLifecycleObserver接口,當組件狀態發生變化時,會調用onStateChanged方法,當組件處於DESTROYED狀態時,會調用註釋1處的removeObserver方法,來移除observer。
這樣在文章開頭的疑問就解決了,爲什麼一個觀察者(組件)處於DESTROYED狀態時,它將不會收到通知。

接着會調用註釋2處的activeStateChange方法,代碼如下所示。

frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

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

activeStateChanged方法定義在抽象類ObserverWrapper中,它是Observer的包裝類,activeStateChanged方法會根據Active狀態和處於Active狀態的組件的數量,來對onActive方法和onInactive方法回調,這兩個方法用於拓展LiveData對象。註釋1處,如果是Active狀態,會調用dispatchingValue方法,並將自身傳進去。

  private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //正在處於分發狀態中
        if (mDispatchingValue) {
            //分發無效
            mDispatchInvalidated = true;//1
            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;
    }

mDispatchingValue用於標記當前是否處於分發狀態中,如果處於該狀態,則在註釋1處標記當前分發無效,直接return。一路調用過來,ObserverWrapper是不爲null的,ObserverWrapper爲null的情況第3小節會講到,無論是那種情況,都會調用considerNotify方法,代碼如下所示。

    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {//1
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);//2
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);//3
    }
    

considerNotify方法中做了多次的判斷,註釋1處,如果ObserverWrapper的mActive值不爲true,就直接return。註釋2處,如果當前observer對應組件的狀態不是Active,就會再次調用activeStateChanged方法,並傳入false,其方法內部會再次判斷是否執行onActive方法和onInactive方法回調。如果判斷條件都滿足會調用Observer的onChanged方法,這個方法正是使用LiveData的observe方法的回調。

3.postValue/setValue方法分析

當調用MutableLiveData的observe方法後,還需要通過postValue/setValue方法來更新數據。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

...
  private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);//1
        }
    };
    ...
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);//2
    }
    
    @MainThread //3
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

postValue/setValue方法都定義在LiveData中,根據註釋1和註釋2處,可以發現postValue方法實際上就是將setValue方法切換到主線程調用。註釋3處說明setValue方法是運行在主線程中的,其內部調用了dispatchingValue方法,這個方法在第2小節介紹過,也就是dispatchingValue方法的參數ObserverWrapper爲null的情況。
從這裏我們可以知道,無論是LiveData的observe方法還是LiveData的postValue/setValue方法都會調用dispatchingValue方法。

4.Transformations.map方法分析

除了以上講的常用的方法之外,還可能會使用到Transformations.map和Transformations.switchMap方法,這裏以Transformations.map爲例。這個方法用來在LiveData對象分發給觀察者之前對其中存儲的值進行更改,
代碼如下所示。
frameworks/support/lifecycle/livedata/src/main/java/androidx/lifecycle/Transformations.java

@MainThread
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();//1
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

Transformations.map方法運行在主線程,註釋1處創建了MediatorLiveData,緊接着調用了它的addSource方法:
support/lifecycle/livedata/src/main/java/androidx/lifecycle/MediatorLiveData.java

  */
    @MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
        Source<S> e = new Source<>(source, onChanged);//1
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) {
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if (existing != null) {
            return;
        }
        if (hasActiveObservers()) {
            e.plug();//2
        }
    }

註釋1處將傳進來的LiveData和onChanged封裝到Source類中,註釋2處調用了Source的plug方法:

 private static class Source<V> implements Observer<V> {
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<? super V> observer) {
            mLiveData = liveData;
            mObserver = observer;
        }

        void plug() {
            mLiveData.observeForever(this);//1
        }

        void unplug() {
            mLiveData.removeObserver(this);
        }

        @Override
        public void onChanged(@Nullable V v) {
            if (mVersion != mLiveData.getVersion()) {
                mVersion = mLiveData.getVersion();
                mObserver.onChanged(v);//2
            }
        }
    }

註釋2處可以看到,Transformations.map方法傳入的Observer的回調在這裏進行處理。註釋1處,Source的plug方法會調用LiveData的observeForever方法,這個和第2小節所講的內容有什麼區別呢?我們再往下看。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);//1
        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);
    }

註釋1處用AlwaysActiveObserver來對Observer進行包裝,緊接着調用AlwaysActiveObserver的activeStateChanged方法,其內部實際調用的是ObserverWrapper的activeStateChanged方法,這個在第二小節已經做了分析,就不再贅述了。來看AlwaysActiveObserver類是如何定義的。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

   private class AlwaysActiveObserver extends ObserverWrapper {
        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }
        @Override
        boolean shouldBeActive() {
            return true;
        }
    }

AlwaysActiveObserver是LiveData的內部類,它繼承自ObserverWrapper,AlwaysActiveObserver是LiveData的內部類和ObserverWrapper的區別就是,它是永遠處於Active狀態的。

5.LiveData關聯類

接下來給出LiveData關聯類的UML圖,看明白這個圖以後,再回去重新閱讀本文,也許你會收穫更多。

ntP8fA.png
可以看到,在講解LiveData時涉及的大部分類都在這個圖中,其中MutableLiveData繼承自LiveData,LifecycleOwner和Observer和LiveData有關聯的關係,ObserverWrapper是Observer的包裝類,因此它們有着關聯的關係,其他的類大家看圖就知道了。


技術官和架構師的聚集地。洞察前沿架構、技術資訊、行業祕聞,聚焦Java、Python、機器學習、大前端等前沿技術。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章