Android架構組件(Architecture Components)之 LiveData詳解

寫在前面

在上一篇文章Android架構組件(Architecture Components)之 Lifecycle詳解中,說到了要想了解LiveData,需要先了解Lifecycle。所以這次就開始來講講LiveData了。希望還沒看過的朋友先看下上一篇文章,因為這篇文章會有一些依賴到上一篇文章的。

LiveData

結構

先來看看LiveData的結構:


livedata.png

LiveData其實是一個抽象類,但它的內部并沒有抽象的方法。我們可以通過MutableLiveData來使用它。它的實現僅僅只是將setValue()postValue()方法設置為public。所以重點還是應該來分析LiveData。除此之外,LiveData還有幾個內部類:

observer.png

和LifecycleRegistry一樣,LiveData內部也維護著一個觀察者列表:mObservers,它的類型是SafeIterableMap<Observer<? super T>, ObserverWrapper>,對應存儲的值是ObserverWrapper,用了裝飾器模式將Observer給包裝起來。為什么要將Observer包裝起來呢?這是因為LiveData允許我們有兩種不同的觀察模式:有生命周期限制的觀察者和一直觀察的觀察者,分別對應著它的兩個子類:LifecycleBoundObserver和AlwaysActiveObserver。兩種不同的方式供我們選擇,給我們帶來了很高的靈活性。

observe()

回到LiveData的方法上,先從使用頻率最高的observe()方法入手。

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

首先要確保該方法是在主線程上調用的,否則會直接拋出異常。接著判斷如果依附的LifecycleOwner目前已經是DESTROYED狀態的話,就直接返回了。緊接著將方法傳入的Observer和LifecycleOwner封裝成一個LifecycleBoundObserver添加到隊列中。最后向LifecycleOwner中注冊了一個觀察者。到這里為止,有了觀察者和被觀察者,整套機制就能運轉起來了。

上一篇文章的最后,講到了dispatchEvent()方法就結束了,再來回顧一下:

void dispatchEvent(LifecycleOwner owner, Event event) {
    State newState = getStateAfter(event);
    mState = min(mState, newState);
    mLifecycleObserver.onStateChanged(owner, event);
    mState = newState;
}

當時說了:

LifecycleObserver是一個LifecycleEventObserver,也是一個接口來著,繼承了LifecycleObserver

結合上面的類圖,LifecycleBoundObserver不僅是繼承了ObserverWrapper,它還實現了LifecycleEventObserver接口。所以當LifecycleOwner的狀態發生變化時,會走到LifecycleBoundObserver的onStateChanged()方法中:

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
    if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
        removeObserver(mObserver);
        return;
    }
    activeStateChanged(shouldBeActive());
}

如果生命周期的狀態變成了DESTROYED,LiveData會自動幫我們移除掉觀察者,避免內存泄漏。

shouldBeActive()是一個抽象方法,來看下它的兩個子類的不同。

// LifecycleBoundObserver
@Override
boolean shouldBeActive() {
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

// AlwaysActiveObserver
@Override
boolean shouldBeActive() {
    return true;
}

LifecycleBoundObserver中,只有當前的狀態至少處于STARTED的才會被認為是活躍的。而AlwaysActiveObserver由于沒有生命周期的概念,所以一直是處于活躍的狀態的。這是它們的區別所在。

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) {
        dispatchingValue(this);
    }
}

這里主要是判斷Observer是否應該處于活躍狀態,如果是的話,才去更新數據。這里又看到了熟悉的dispatchXXX()方法。

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

重點在considerNotify()方法上:

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

在這里會最后一次去檢查Observer是否處于激活狀態,并且目前的新的數據版本是否比當前高,條件都滿足的話就會通知Observer更新數據了。

observeForever()

除了observe()方法外,還有一個observeForever()方法。這個比較簡單,就是普通的觀察者模式。使用這個方法,一定要注意,要在恰當的時機,通過removeObserver()或者removeObservers()將觀察者移除掉,否則很可能會發生內存泄漏。

setValue()

通過LifecycleOwner的生命周期變化來決定是否要通知觀察者,這只是LiveData通知觀察者的一種方式。當數據發生變化時,LiveData也會通知觀察者。

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

當數據發生變化時,會更新版本號,然后又是調用了dispatchingValue(),流程還是和上面的一樣,就不再講下去了。

postValue()

上面的setValue()要求在主線程中調用,如果是在子線程想更新數據的話,可以使用這個方法。

寫在最后

和上一篇的LifecycleOwner結合起來,總算是把這套加入生命周期的觀察者模式給理清了。剩下的就差ViewModel還沒有分析了。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容