Android架構(gòu)組件(Architecture Components)之 Lifecycle詳解

前言

在Android推出的架構(gòu)組件Architecture Components中,LiveData和ViewModel無疑是最核心的。它們最神奇的地方就在于:

  1. LiveData:能夠在數(shù)據(jù)發(fā)生變化時及時通知View去更新界面,并且如果當界面不可見或者被銷毀時刨秆,LiveData是不會通知UI的降宅。言下之意,LiveData是能夠感知生命周期的已卸。
  2. ViewModel:它能夠為我們保存數(shù)據(jù),即使Activity由于某些原因需要重建镇眷,保存在ViewModel中的數(shù)據(jù)也不會因此被銷毀咬最。這帶來的好處就是頁面重建后,數(shù)據(jù)無需重新加載欠动,直接用原來保存下來的數(shù)據(jù)即可永乌。

但其實在它們的背后還有一個默默付出的Lifecycle,可以說Lifecycle才是這個架構(gòu)的靈魂具伍。

Lifecycle

前面說了翅雏,LiveData是可以感知Android生命周期的,而LiveData是通過Lifecycle來感知生命周期的人芽。從Lifecycle的字面意思來看望几,它就是跟生命周期有直接關(guān)系的。我們知道萤厅,具有Android生命周期的最常見的就是Activity和Fragment橄抹。所以要想了解LiveData,需要先了解Android的生命周期是如何傳遞給Lifecycle的才行惕味。下面這些例子都是以Fragment來展開分析的楼誓。
在剛接觸這個框架的時候,出現(xiàn)了很多與Lifecycle有關(guān)的類名挥,比如說:LifecycleOwner, LifeCycle, LifecycleRegistry, LifecycleObserver...講真的疟羹,對于一個不熟悉的東西,一下子又扔過來這么幾個看起來有點關(guān)聯(lián)的東西禀倔,頭是有點大的榄融。所以有必要花些時間來理一理這些東西先。先上一張類圖(這里只是把一些比較重要的屬性和方法羅列出來):

lifecycle.png
  • LifecycleOwner:這是一個接口救湖,它只有一個方法getLifecycle()愧杯。從名字上理解它就是一個擁有生命周期的組件,比如說Fragment鞋既,所以Fragment實現(xiàn)了這個接口民效,也可以這么理解,F(xiàn)ragment就是一個生命周期的擁有者涛救。
  • Lifecycle:這是一個抽象類畏邢。主要是添加和移除觀察者,和獲得當前生命周期的狀態(tài)检吆。它還有兩個內(nèi)部的枚舉類:State和Event舒萎,分別表示生命周期的狀態(tài)和相應(yīng)的事件。
  • LifecycleObserver:這是一個接口蹭沛,并且是空的臂寝,暫時知道它是一個觀察者就好了章鲤。
  • LifecycleRegistry:這個類繼承了Lifecycle類并實現(xiàn)了所有的方法。成員變量mObserverMap用來管理觀察者隊列咆贬。handleLifecycleEvent()方法用來設(shè)置當前的生命周期狀態(tài)败徊,并通知觀察者更新狀態(tài)。LifecycleOwner需要通過handleLifecycleEvent()這個方法掏缎,將自己的生命周期狀態(tài)傳遞給Lifecycle皱蹦,從而讓Lifecycle擁有感知生命周期的能力。
  • Fragment:它有一個mLifecycleRegistry屬性, 類型正是Lifecycle眷蜈。實現(xiàn)的getLifecycle()就是返回了mLifecycleRegistry沪哺。

用一句話來解釋它們之間的聯(lián)系就是:Fragment是一個LifecycleOwner,它在自己的生命周期的各個階段中酌儒,通過mLifecycleRegistry辜妓,將自己的狀態(tài)告訴了Lifecycle,讓Lifecycle擁有了感知生命周期的能力忌怎。

講到這里了籍滴,再來深入一下研究LifecycleRegistry$handleLifecycleEvent()這個方法吧×裥ィ看之前得先知道下mObserverMap的結(jié)構(gòu)孽惰。

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
        new FastSafeIterableMap<>();

這是一個特殊的Map,它能夠在遍歷的時候執(zhí)行添加或者刪除操作插掂。它的key值是LifecycleObserver灰瞻,沒什么好說的腥例。value值是ObserverWithState辅甥,在addObserver()的時候,會將LifecycleObserver和初始狀態(tài)State封裝成一個ObserverWithState然后放進value值中燎竖。OK璃弄,這只是一個小插曲而已,有助于我們后面的理解构回,接著進入正題吧夏块。

/**
 * Sets the current state and notifies the observers.
 * <p>
 * Note that if the {@code currentState} is the same state as the last call to this method,
 * calling this method has no effect.
 *
 * @param event The event that was received
 */
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    State next = getStateAfter(event);
    moveToState(next);
}

收到一個事件后,根據(jù)當前的事件獲取下一個狀態(tài)纤掸,然后跳轉(zhuǎn)到下一個狀態(tài)脐供。

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;
    }
    mHandlingEvent = true;
    sync();
    mHandlingEvent = false;
}

代碼也很簡單,一眼就能看出重點在sync()方法上借跪。

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;
    }
    while (!isSynced()) {
        mNewEventOccurred = false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

方法內(nèi)先是判斷LifecycleOwner是否被回收政己,接著再判斷所有的觀察者狀態(tài)是否都同步了。判斷依據(jù)是最新的觀察者和最老的觀察者之間狀態(tài)是否一致掏愁。

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

如果還沒有完成同步歇由,則走while循環(huán)繼續(xù)同步卵牍。可以看到循環(huán)體內(nèi)有backwardPass()forwardPass()沦泌,我們只看一個就好了糊昙,之所以會有兩個,是因為FastSafeIterableMap這個數(shù)據(jù)結(jié)構(gòu)的特性決定的谢谦。

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));
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
        }
    }
}

外面的都是一些判斷释牺,直接看到observer.dispatchEvent(lifecycleOwner, event)這里,看到dispatchXXX有沒有覺得有點熟悉和激動他宛?需要注意的是這里的observer是一個ObserverWithState來著船侧。

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

看到這里,總算可以有個了結(jié)了厅各。LifecycleObserver通過onStateChanged()方法將狀態(tài)改變發(fā)送給了觀察者镜撩,觀察者由此可以得知Android生命周期的變化。

等等队塘,好像哪里不對袁梗。上面不是說LifecycleObserver是一個空接口嗎?怎么這里就冒出了onStateChanged()這個方法來了憔古?這不是打自己的臉嗎遮怜?
其實這里的LifecycleObserver是一個LifecycleEventObserver,也是一個接口來著鸿市,繼承了LifecycleObserver锯梁,另外還有一個FullLifecycleObserver也繼承了LifecycleObserver。

lifecycleobserver.png

展望未來

這里僅僅只是做了一個開篇焰情,為接下來分析LiveData和ViewModel做鋪墊陌凳,為了不讓自己拖太久,先來一篇Lifecycle的分析打打雞血内舟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末合敦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子验游,更是在濱河造成了極大的恐慌充岛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕蝉,死亡現(xiàn)場離奇詭異崔梗,居然都是意外死亡,警方通過查閱死者的電腦和手機垒在,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門蒜魄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事权悟≡彝酰” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵峦阁,是天一觀的道長谦铃。 經(jīng)常有香客問我,道長榔昔,這世上最難降的妖魔是什么驹闰? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮撒会,結(jié)果婚禮上嘹朗,老公的妹妹穿的比我還像新娘。我一直安慰自己诵肛,他們只是感情好屹培,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怔檩,像睡著了一般褪秀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上薛训,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天媒吗,我揣著相機與錄音,去河邊找鬼乙埃。 笑死闸英,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的介袜。 我是一名探鬼主播甫何,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼米酬!你這毒婦竟也來了沛豌?” 一聲冷哼從身側(cè)響起趋箩,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赃额,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后叫确,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跳芳,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年竹勉,在試婚紗的時候發(fā)現(xiàn)自己被綠了飞盆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吓歇,靈堂內(nèi)的尸體忽然破棺而出孽水,到底是詐尸還是另有隱情,我是刑警寧澤城看,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布女气,位于F島的核電站,受9級特大地震影響测柠,放射性物質(zhì)發(fā)生泄漏炼鞠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一轰胁、第九天 我趴在偏房一處隱蔽的房頂上張望谒主。 院中可真熱鬧,春花似錦赃阀、人聲如沸霎肯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姿现。三九已至,卻和暖如春肖抱,著一層夾襖步出監(jiān)牢的瞬間备典,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工意述, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留提佣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓荤崇,卻偏偏與公主長得像拌屏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子术荤,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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