Jetpack 組件之 Lifecycle 使用與淺析

Lifecycle 是什么手负?

官方解釋:

Lifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state.

個人理解:
Lifecycle 就是管理組件( Activity / Fragment )生命周期的一個工具(類),可以在其他組件( Activity / Fragment 之外)監(jiān)聽生命周期變化姑尺。該組件是 Jetpack 架構(gòu)組件庫(Jetpack Architecture Components)中非常重要的一部分竟终,例如 LiveData、ViewModel 等組件切蟋,必須依賴該組件實現(xiàn)監(jiān)聽和處理生命周期變化统捶。

怎么使用 Lifecycle?

DefaultLifecycleObserver方式:[推薦]

前提

  • 項目使用Java 8 進行編譯
  • 添加 gradle 依賴 "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        //注冊生命周期監(jiān)聽
        lifecycle.addObserver(ActivityLifecycleObserver())
    }
}

/**
* 生命周期的監(jiān)聽類
* 可實現(xiàn)生命周期相關(guān)邏輯柄粹,使 LoginActivity 中的代碼邏輯更加簡潔
*/
class ActivityLifecycleObserver: DefaultLifecycleObserver{

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        //生命周期執(zhí)行到了 onResume
    }
}

注解方式:

不推薦瘾境。注解方式是通過反射調(diào)用,存在性能損耗镰惦。

class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        //注冊生命周期監(jiān)聽
        lifecycle.addObserver(ActivityLifecycleObserver())
    }
}

/**
* 生命周期的監(jiān)聽類
* 可實現(xiàn)生命周期相關(guān)邏輯,使 LoginActivity 中的代碼邏輯更加簡潔
*/
class ActivityLifecycleObserver: LifecycleObserver{
    
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onResume(){
        //生命周期執(zhí)行到了 onResume
    }
}

拓展犬绒,自主管理生命周期

非常不推薦旺入。這種自行維護生命周期,可能會出現(xiàn)競態(tài)情況凯力。

class LoginActivity : AppCompatActivity() {

    private lateinit var mLifecycleRegistry: LifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        
        //這里自定義LifecycleRegistry
        mLifecycleRegistry = LifecycleRegistry(this)
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)

        //注冊生命周期監(jiān)聽
        lifecycle.addObserver(ActivityLifecycleObserver())
    }

    override fun onStart() {
        super.onStart()
        //通過自定義的 LifecycleRegistry 發(fā)送生命周期茵瘾,可覆蓋默認實現(xiàn)
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
    }

    // 必須要重寫該方法,賦予自定義的Registry
    override fun getLifecycle(): Lifecycle {
        return mLifecycleRegistry
    }
}

class ActivityLifecycleObserver: LifecycleObserver{

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onResume(){
        //生命周期執(zhí)行到了 onResume
    }
}

Lifecycle 的原理是什么咐鹤?

理解 Event拗秘、State

在開始源碼講解前,首先要明白 Event 與 State 之間的關(guān)系祈惶。這個至關(guān)重要雕旨,因為在源碼中經(jīng)常會有 Event 與 State 間的互相轉(zhuǎn)換扮匠,需要依賴兩者的關(guān)系圖()促進理解才行。

Event: Lifecycle 發(fā)送對應(yīng)的生命周期事件的枚舉類凡涩,包含 onCreate棒搜、onStart 等生命周期事件。

State: Lifecycle 處理的生命周期狀態(tài)活箕,與Event是映射關(guān)系力麸。

State與Event關(guān)系映射圖.jpg

實現(xiàn)原理

原理僅講解 Activity 部分,F(xiàn)ragment 的實現(xiàn)邏輯育韩,可自行查看下 FragmentActivity # HostCallbacks 類的相關(guān)調(diào)用與邏輯克蚂。

源碼部分基于 lifecycle 2.2.0 版本 與 acitivity 1.1.0 版本。

源碼分析分為兩部分筋讨,先從調(diào)用方法出發(fā)埃叭,大體知道內(nèi)部邏輯,再從疑問入手版仔,解答心里疑惑游盲。

從調(diào)用方法出發(fā)

/**
* 這里有三部分組成: lifecycle、addObserver()蛮粮、ActivityLifecycleObserver對象
* lifecycle: 對應(yīng)的 getLifecycle() 方法,獲取 Lifecycle 對象
* addObserver(): 調(diào)用 Lifecycle 對象的 addObserver() 方法
* ActivityLifecycleObserver對象: 這個是我們實現(xiàn) DefaultLifecycleObserver 接口的類對象
*/
lifecycle.addObserver(ActivityLifecycleObserver())

通過調(diào)用方法可以發(fā)現(xiàn),需要看一下 getLifecycle() 和 addObserver() 兩個方法的內(nèi)部邏輯是什么莺奔?

getLifecycle() 內(nèi)部實現(xiàn):

通過下面代碼可以看到变泄,getLifecycle() 方法真正實現(xiàn)是在 ComponentActivity中令哟,并且創(chuàng)建一個 LifecycleRegistry 對象,通過該方法返回妨蛹。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner{
    // ... 省略 ...

    // 直接 new 了一個 LifecycleRegistry 對象。
    // LifecycleRegistry 這個類又是做什么的呢蛙卤? 這個我們后面在看。
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    // ... 省略 ...

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

    // ... 省略 ...

}

addObserver() 內(nèi)部實現(xiàn):

通過代碼可以發(fā)現(xiàn) LifecycleRegistry 才是實際的生命周期的管理類颤难,這也是為什么上面 getLifecycle() 返回的是LifecycleRegistry 對象神年。代碼看起來不少,但也是最核心的部分已日,簡單總結(jié)下:

  1. 調(diào)用 addObserver() 方法栅屏,內(nèi)部會給定一個初始狀態(tài)堂鲜,并與 observer 綁定(通過 ObserverWithState)占婉,然后調(diào)用了 sync() 方法。
  2. sync() 方法內(nèi)部根據(jù)狀態(tài)之間的差異判斷是往前走(forwardPass())還是往后走(backwardPass())逆济。(此處咱們以往前走為例)
  3. forwardPass()內(nèi)部調(diào)用 upEvent() 方法,將 observer 的 State 轉(zhuǎn)換為 Event抛虫,然后調(diào)用 ObserverWithState#dispatchEvent() 進行分發(fā)简僧。
  4. 此時我們自己實現(xiàn)的 Observer 類就會收到生命周期回調(diào)了。

PS: 這里需要注意 LifecycleRegistry#mState 和 ObserverWithState#mState 不要搞混了棉姐。

public class LifecycleRegistry extends Lifecycle {

    // ... 省略 ...

    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {

        // 給定一個初始狀態(tài)啦逆,創(chuàng)建 ObserverWithState 對象伞矩,將狀態(tài)與 observer 傳入夏志,
        // 然后將 ObserverWithState 對象存入 map 中
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        // ... 省略 ...

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
            
        // ... 省略 ...
    }

    // ... 省略 ...

    private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    
        // ... 省略 ...
    
        // 通過 isSynced() 方法判斷狀態(tài)是否已經(jīng)對齊沟蔑。
        // 下面邏輯用于判斷是往前走,還是往后走瘦材。
        // 需要借助“State 與 Event 關(guān)系圖”來理解。
        // 例如:
        // 顯示一個新建的Activity, mState = Created, mObserverMap.eldest().getValue().mState = INITIALIZED, 
        // newest.getValue().mState = INITIALIZED食棕。通過以下邏輯可以判斷宣蠕,執(zhí)行 forwardPass() 方法(往前走)
        while (!isSynced()) {
            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);
            }
        }
    }

    // ... 省略 ...

    private void forwardPass(LifecycleOwner lifecycleOwner) {
        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);

                // 重點在這里~ 調(diào)用 upEvent() 方法甥捺,獲取當前 State 對應(yīng)的 Event,
                // 然后調(diào)用 ObserverWithState 的 dispatchEvent() 方法分發(fā)
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));

                popParentState();
            }
        }
    }

    // ... 省略 ...

    // State 轉(zhuǎn) Event镰禾∶笄可參照“State 與 Event 關(guān)系圖”來理解
    private static Event upEvent(State state) {
        switch (state) {
            case INITIALIZED:
            case DESTROYED:
                return ON_CREATE;
            case CREATED:
                return ON_START;
            case STARTED:
                return ON_RESUME;
            case RESUMED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value " + state);
    }

    // ... 省略 ...


    // 靜態(tài)內(nèi)部類屋休,用于綁定 observer 與 State
    static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {

            // 這里將自己實現(xiàn)的 Observer 類對象做了一層轉(zhuǎn)換。內(nèi)部有對注解方式的實現(xiàn)劫樟,可自行查看叠艳。
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);

            mState = initialState;
        }


        // 通過 Event 轉(zhuǎn) State,對當前 Event 事件進行下發(fā)附较,并更新 observer 的 State
        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

    // ... 省略 ...
}

從疑問出發(fā)

1. Lifecycle 是如何監(jiān)聽生命周期的拒课?又怎么通知其他組件(Observer)生命周期變化的?

從上面的“從調(diào)用方法入手”沒有看到如何監(jiān)聽生命周期變化的早像,那么這一塊邏輯在哪里呢扎酷?
(這里以 監(jiān)聽 Activity 生命周期為例) 在 ComponentActivity#onCreate() 方法中調(diào)用了 ReportFragment#injectIfNeededIn()。ReportFragment 就是真正的生命周期提供者(被觀察者)法挨,它內(nèi)部提供生命周期的變化凡纳,并調(diào)用 LifecycleRegistry#handleLifecycleEvent() 方法進行下發(fā)。handleLifecycleEvent() 方法內(nèi)部將 Event 轉(zhuǎn) State荐糜,然后調(diào)用 sync 方法,剩余邏輯就和“從調(diào)用方法觸發(fā)”中的一樣了(可以看 addObserver() 內(nèi)部實現(xiàn) 部分)延塑。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {
    // ... 省略 ...

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedStateRegistryController.performRestore(savedInstanceState);

        // 這里
        ReportFragment.injectIfNeededIn(this);
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }

}

//實際生命周期被觀察者
public class ReportFragment extends Fragment {
    // ... 此處省略生命周期相關(guān)邏輯答渔,最后都會調(diào)用 dispatch() ...

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();

        // ... 省略 ...

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {

                    //調(diào)用 LifecycleRegistry#handleLifecycleEvent() 方法觸發(fā)事件
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }
        
}

public class LifecycleRegistry extends Lifecycle {
    // ... 省略 ...

    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        // 根據(jù)傳入的 Event 獲取 State
        State next = getStateAfter(event);
        moveToState(next);
    }

    // 更新 LifecycleRegistry#mState 值沼撕,然后調(diào)用 sync() 方法
    private void moveToState(State next) {
        // ... 省略 ...
        
        mState = next;

        // ... 省略 ...

        sync();
    }

    // ... 省略 ...

}

2. addObserver() 在 onStart() 中調(diào)用的話宋雏,還會受到 onCreate 生命周期嗎?

通過如下代碼和注釋可以得出結(jié)論:如果不是在 onCreate() 中調(diào)用 addObserver()嗦明,仍然可以得到生命周期事件蚪燕。

public class LifecycleRegistry extends Lifecycle {

    // ... 省略 ...

    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {

        // ... 省略 ...
        
        // 這里開始比較 observer 的 State 與當前的 State,如果晚于當前的 State 則觸發(fā) dipatchEvent 追趕當前的生命周期裙戏。
        // 比較兩個 State 的意義在于 addObserver() 調(diào)用如果不在 onCreate 中厕诡,則仍可以接收到 onCreate 生命周期。
        // 例如:
        // 當前的 State = Started, observer 的 State = INITIALIZED壹罚,
        // observer 的 State 晚于當前的 State寿羞,則觸發(fā) dispatchEvent(INITIALIZED)
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // 為了防止在observer State 在追趕途中,當前 State 又發(fā)生了變化辨泳,則調(diào)用 calculateTargetState() 再次計算一下兩者差距
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
            
        // ... 省略 ...
    }
    
    // ... 省略 ...
}

3. 項目現(xiàn)在繼承的是 Activity 類玖院,怎么使用 Lifecycle 呢?

通過代碼可以得知试溯,Lifecycle 的生命周期變化是在 ComponentActivity郊酒,如果繼承的是 Activity,那只能自己維護生命周期的變化燎窘,類似于“拓展褐健,自主管理生命周期”,區(qū)別在于需要實現(xiàn) LifecycleOwner 接口,并維護全生命周期。以下為示例代碼:

open class BaseActivity : Activity(), LifecycleOwner{

    private val mLifecycleRegistry = LifecycleRegistry(this)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
    }
    
    override fun onStart() {
        super.onStart()
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
    }
    
    override fun onDestroy() {
        super.onDestroy()
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    }
    
    override fun getLifecycle(): Lifecycle {
        return mLifecycleRegistry
    }
}

總結(jié)

簡單總結(jié)下Lifecycle的實現(xiàn)原理:在 ComponentActivity 調(diào)用 ReportFragment 來監(jiān)聽生命周期變化慢叨,當生命周期變化時,調(diào)用 LifecycleRegistry#handleLifecycleEvent() 來通知烛缔。然后調(diào)用 LifecycleRegistry#addObserver() 方法轩拨,內(nèi)部會根據(jù) State 與 Event 進行轉(zhuǎn)換,并下發(fā)生命周期事件亡蓉。
下面為調(diào)用時序圖,可參照自行走一遍源碼淋肾。


Lifecycle時序圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末樊卓,一起剝皮案震驚了整個濱河市杠河,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌券敌,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颈走,死亡現(xiàn)場離奇詭異咱士,居然都是意外死亡序厉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門道盏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荷逞,你說我怎么就攤上這事≈衷叮” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵妙同,是天一觀的道長膝迎。 經(jīng)常有香客問我,道長芒涡,這世上最難降的妖魔是什么掂恕? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮依啰,結(jié)果婚禮上店枣,老公的妹妹穿的比我還像新娘。我一直安慰自己闷旧,他們只是感情好钧唐,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著该园,像睡著了一般帅韧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上忽舟,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音泣特,去河邊找鬼挑随。 笑死,一個胖子當著我的面吹牛镀裤,可吹牛的內(nèi)容都是我干的缴饭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼担猛,長吁一口氣:“原來是場噩夢啊……” “哼丢氢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蒸走,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤貌嫡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后别惦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夫椭,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年扰付,在試婚紗的時候發(fā)現(xiàn)自己被綠了悯周。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陪竿。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡屠橄,死狀恐怖闰挡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溪北,我是刑警寧澤夺脾,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蚀乔,受9級特大地震影響菲茬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜婉弹,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一镀赌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧佩脊,春花似錦、人聲如沸出牧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伯复。三九已至邢笙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氮惯,已是汗流浹背想暗。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工说莫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寞焙,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓辽狈,卻偏偏與公主長得像呛牲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侈净,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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