關(guān)于LiveData 的源碼分析

前言

在 Lifecycle-aware Components 源碼分析 一文中考阱,我們已經(jīng)分析了 Lifecycle 框架中所有的 lifecyle 事件產(chǎn)生流程以及分發(fā)流程。本文將會基于這部分知識來分析 Lifecycle 框架中的 LiveData 組件。

提出問題

結(jié)合 LiveData javadoc, LiveData 文檔匀归,我們可以了解到 LiveData 主要作用是數(shù)據(jù)發(fā)生變化時通知 Observer食店,那么 LiveData 是如何實現(xiàn)這部分內(nèi)容的呢罪郊?

LiveData

observe

有監(jiān)聽得先有注冊,先來看 observe 方法:

@MainThread

public void observe(LifecycleOwner owner, Observer<T> observer) {

? if (owner.getLifecycle().getCurrentState() == DESTROYED) {

? ? ? // ignore

? ? ? return;

? }

? LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

? LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);

? if (existing != null && existing.owner != wrapper.owner) {

? ? ? throw new IllegalArgumentException("Cannot add the same observer"

? ? ? ? ? ? ? + " with different lifecycles");

? }

? if (existing != null) {

? ? ? return;

? }

? owner.getLifecycle().addObserver(wrapper);

? wrapper.activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));

}

observe 方法需運行在主線程中梢灭,執(zhí)行時會將 Observer 傳入 LifecycleBoundObserver,并將 LifecycleBoundObserver 通過 addObserver 注冊至 Lifecycle蒸其,緊接著調(diào)用了 LifecycleBoundObserver 的 activeStateChanged 方法敏释。

LifecycleBoundObserver

接著看 LifecycleBoundObserver:

class LifecycleBoundObserver implements LifecycleObserver {

? public final LifecycleOwner owner;

? public final Observer<T> observer;

? public boolean active;

? public int lastVersion = START_VERSION;

? LifecycleBoundObserver(LifecycleOwner owner, Observer<T> observer) {

? ? ? this.owner = owner;

? ? ? this.observer = observer;

? }

? @SuppressWarnings("unused")

? @OnLifecycleEvent(Lifecycle.Event.ON_ANY)

? void onStateChange() {

? ? ? if (owner.getLifecycle().getCurrentState() == DESTROYED) {

? ? ? ? ? removeObserver(observer);

? ? ? ? ? return;

? ? ? }

? ? ? // immediately set active state, so we'd never dispatch anything to inactive

? ? ? // owner

? ? ? activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));

? }

? void activeStateChanged(boolean newActive) {

? ? ? if (newActive == active) {

? ? ? ? ? return;

? ? ? }

? ? ? active = newActive;

? ? ? boolean wasInactive = LiveData.this.mActiveCount == 0;

? ? ? LiveData.this.mActiveCount += active ? 1 : -1;

? ? ? if (wasInactive && active) {

? ? ? ? ? onActive();

? ? ? }

? ? ? if (LiveData.this.mActiveCount == 0 && !active) {

? ? ? ? ? onInactive();

? ? ? }

? ? ? if (active) {

? ? ? ? ? dispatchingValue(this);

? ? ? }

? }

}

static boolean isActiveState(State state) {

? return state.isAtLeast(STARTED);

}

不難看出 onStateChange 會接收所有的 lifecycle 事件。當(dāng) LifecycleOwner 的狀態(tài)處于 STARTED 或 RESUMED 時摸袁,傳入 activeStateChanged 的值為 true钥顽,即 LifecycleBoundObserver 會被標(biāo)記為激活狀態(tài),同時會增加 LiveData 的 mActiveCount 計數(shù)靠汁。接著可以看到蜂大,onActive 會在 mActiveCount 為 1 時觸發(fā),onInactive 方法則只會在 mActiveCount 為 0 時觸發(fā)蝶怔。這里就與 LiveData javadoc 所描述的完全吻合(In addition, LiveData has onActive() and onInactive() methods to get notified when number of active Observers change between 0 and 1. This allows LiveData to release any heavy resources when it does not have any Observers that are actively observing.)奶浦。

dispatchingValue

此后,如果 LifecycleBoundObserver 處于激活狀態(tài)添谊,則會調(diào)用 dispatchingValue:

private void dispatchingValue(@Nullable LifecycleBoundObserver initiator) {

? if (mDispatchingValue) {

? ? ? mDispatchInvalidated = true;

? ? ? return;

? }

? mDispatchingValue = true;

? do {

? ? ? mDispatchInvalidated = false;

? ? ? if (initiator != null) {

? ? ? ? ? considerNotify(initiator);

? ? ? ? ? initiator = null;

? ? ? } else {

? ? ? ? ? for (Iterator<Map.Entry<Observer<T>, LifecycleBoundObserver>> iterator =

? ? ? ? ? ? ? ? ? mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {

? ? ? ? ? ? ? considerNotify(iterator.next().getValue());

? ? ? ? ? ? ? if (mDispatchInvalidated) {

? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? }

? ? ? ? ? }

? ? ? }

? } while (mDispatchInvalidated);

? mDispatchingValue = false;

}

其中 mDispatchingValue, mDispatchInvalidated 只在 dispatchingValue 方法中使用财喳,顯然這兩個變量是為了防止重復(fù)分發(fā)相同的內(nèi)容。

considerNotify

接下來,無論哪個路徑都會調(diào)用 considerNotify:

private void considerNotify(LifecycleBoundObserver observer) {

? if (!observer.active) {

? ? ? 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 (!isActiveState(observer.owner.getLifecycle().getCurrentState())) {

? ? ? return;

? }

? if (observer.lastVersion >= mVersion) {

? ? ? // 數(shù)據(jù)已經(jīng)是最新

? ? ? return;

? }

? observer.lastVersion = mVersion;

? //noinspection unchecked

? observer.observer.onChanged((T) mData);

}

注:mVersion 代表的是數(shù)據(jù)變化的次數(shù)耳高,下文會補充說明扎瓶。

顯然 considerNotify 的作用就是通知處于激活狀態(tài)且數(shù)據(jù)未更新的 Observer 數(shù)據(jù)已發(fā)生變化。

其中 mData 即是 LiveData 當(dāng)前的數(shù)據(jù)泌枪,默認(rèn)是一個全局 Object:

private static final Object NOT_SET = new Object();

private Object mData = NOT_SET;

可能會有人擔(dān)心當(dāng) LiveData 的 mData 未發(fā)生變更時概荷,第一次調(diào)用 observe 會將 NOT_SET 傳遞到 Observer 中。事實上并不會碌燕,因為 LiveData 的 mVersion 和 LifecycleBoundObserver 的 lastVersion 的默認(rèn)值均為 START_VERSION:

public abstract class LiveData<T> {

? ? ...

? ? static final int START_VERSION = -1;

? ? private int mVersion = START_VERSION;

? ? ...

? ? class LifecycleBoundObserver implements LifecycleObserver {

? ? ? ? ...

? ? ? ? public int lastVersion = START_VERSION;

? ? ? ? ...

? ? }

? ? ...

}

在 observer.lastVersion >= mVersion 判斷時就會直接返回而不執(zhí)行 observer.observer.onChanged((T) mData)误证。

setValue

再來看 setValue:

@MainThread

protected void setValue(T value) {

? assertMainThread("setValue");

? mVersion++;

? mData = value;

? dispatchingValue(null);

}

setValue 與 observe 方法一樣均需要在主線程上執(zhí)行,當(dāng) setValue 的時候 mVersion 的值會自增修壕,并通知 Observer 數(shù)據(jù)發(fā)生變化愈捅。

postValue

setValue 還有另一個替代的方法 postValue:

protected void postValue(T value) {

? boolean postTask;

? synchronized (mDataLock) {

? ? ? postTask = mPendingData == NOT_SET;

? ? ? mPendingData = value;

? }

? if (!postTask) {

? ? ? return;

? }

? AppToolkitTaskExecutor.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);

? }

};

其中 AppToolkitTaskExecutor 是通過一個以 Main Looper 作為 Looper 的 Handler 將 mPostValueRunnable 運行在主線程上,所以 postValue 可以運行在任意線程上慈鸠,而 Observer 的 OnChange 回調(diào)會執(zhí)行在主線程上蓝谨。

observeForever

最后再看下 observeForever

@MainThread

public void observeForever(Observer<T> observer) {

? observe(ALWAYS_ON, observer);

}

private static final LifecycleOwner ALWAYS_ON = new LifecycleOwner() {

? private LifecycleRegistry mRegistry = init();

? private LifecycleRegistry init() {

? ? ? LifecycleRegistry registry = new LifecycleRegistry(this);

? ? ? registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);

? ? ? registry.handleLifecycleEvent(Lifecycle.Event.ON_START);

? ? ? registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);

? ? ? return registry;

? }

? @Override

? public Lifecycle getLifecycle() {

? ? ? return mRegistry;

? }

};

可以看到,observeForever 將 Observer 注冊了在一個永遠(yuǎn)處于 RESUMED 的 LifecycleOwner 中青团,所以通過 observeForever 注冊的 Observer 需要通過 removeObserver 來取消數(shù)據(jù)變化的監(jiān)聽譬巫。

總結(jié)

至此,我們已經(jīng)明白 LiveData 主要是通過 LifecycleBoundObserver 與 Lifecycle 結(jié)合來控制數(shù)據(jù)的分發(fā)督笆。

LiveData 的代碼比 Lifecycle 要簡單得多芦昔,主要是有了 Lifecycle 部分的分析作為基礎(chǔ),看起來很輕松娃肿。

附《Android核心知識筆記2020》分享

前段時間我和圈子里的幾位架構(gòu)師朋友一起閑聊時的突發(fā)奇想咕缎,我們在學(xué)習(xí)Android開發(fā)的時候或多或少也受到了一些前輩的指導(dǎo),所以想把這份情懷延續(xù)下去咸作。三個月后锨阿,這套資料就出來了,需要這份資料的朋友加Android學(xué)習(xí)交流群1049273031即可獲取记罚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末墅诡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子桐智,更是在濱河造成了極大的恐慌末早,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件说庭,死亡現(xiàn)場離奇詭異然磷,居然都是意外死亡,警方通過查閱死者的電腦和手機刊驴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門姿搜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寡润,“玉大人,你說我怎么就攤上這事舅柜∷笪疲” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵致份,是天一觀的道長变抽。 經(jīng)常有香客問我,道長氮块,這世上最難降的妖魔是什么绍载? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮滔蝉,結(jié)果婚禮上击儡,老公的妹妹穿的比我還像新娘。我一直安慰自己锰提,他們只是感情好曙痘,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著立肘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪名扛。 梳的紋絲不亂的頭發(fā)上谅年,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音肮韧,去河邊找鬼融蹂。 笑死,一個胖子當(dāng)著我的面吹牛弄企,可吹牛的內(nèi)容都是我干的超燃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼拘领,長吁一口氣:“原來是場噩夢啊……” “哼意乓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起约素,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤届良,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后圣猎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體士葫,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年送悔,在試婚紗的時候發(fā)現(xiàn)自己被綠了慢显。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爪模。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荚藻,靈堂內(nèi)的尸體忽然破棺而出屋灌,到底是詐尸還是另有隱情,我是刑警寧澤鞋喇,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布声滥,位于F島的核電站,受9級特大地震影響侦香,放射性物質(zhì)發(fā)生泄漏落塑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一罐韩、第九天 我趴在偏房一處隱蔽的房頂上張望憾赁。 院中可真熱鬧,春花似錦散吵、人聲如沸龙考。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晦款。三九已至,卻和暖如春枚冗,著一層夾襖步出監(jiān)牢的瞬間缓溅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工赁温, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坛怪,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓股囊,卻偏偏與公主長得像袜匿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子稚疹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容