Android官方架構組件Lifecycle:生命周期組件詳解&原理分析

概述

在過去的谷歌IO大會上,Google官方向我們推出了 Android Architecture Components,其中談到Android組件處理生命周期的問題,向我們介紹了 Handling Lifecycles

同時,如何利用 android.arch.lifecycle 包提供的類來控制數據、監聽器等的 lifecycle。同時,LiveDataViewModel 的 lifecycle 也依賴于 Lifecycle 框架。

經過公司內部的技術交流小組的探討后,不少小伙伴覺得這個框架本身尚未成熟(當時的 Android Architecture Components組件還處于Alpha版本),再加上本身并沒有足夠的說服力讓我們拋棄RxJava+RxAndroid全家桶轉身投奔LiveData ,而Room 這個數據庫框架本身也有很多同樣優秀的三方庫可以替代,因此我漸漸把這個框架的學習計劃擱置了。

不久前, Android Architecture Components 正式Release, Lifecycle也正式植入進了SupportActivity(AppCompatActivity的基類)和Fragment中,我覺得還是有必要去嘗試學習google的這個框架,不管有沒有用到,我相信其本身的設計思想也會對我有很大的幫助。

一、Lifecycle簡介&基礎使用

為什么要引進Lifecycle?

我們在處理Activity或者Fragment組件的生命周期相關時,不可避免會遇到這樣的問題:

我們在Activity的onCreate()中初始化某些成員(比如MVP架構中的Presenter,或者AudioManager、MediaPlayer等),然后在onStop中對這些成員進行對應處理,在onDestroy中釋放這些資源,這樣導致我們的代碼也許會像這樣:

class MyPresenter{
    public MyPresenter() {
    }

    void create() {
        //do something
    }

    void destroy() {
        //do something
    }
}

class MyActivity extends AppCompatActivity {
    private MyPresenter presenter;

    public void onCreate(...) {
        presenter= new MyPresenter ();
        presenter.create();
    }

    public void onDestroy() {
        super.onDestroy();
        presenter.destory();
    }
}

代碼沒有問題,關鍵問題是,實際生產環境中 ,這樣的代碼會非常復雜,你最終會有太多的類似調用并且會導致 onCreate() 和 onDestroy() 方法變的非常臃腫。

解決方案

Lifecycle 是一個類,它持有關于組件(如 Activity 或 Fragment)生命周期狀態的信息,并且允許其他對象觀察此狀態。

我們只需要2步:

1、Prestener繼承LifecycleObserver接口

public interface IPresenter extends LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreate(@NotNull LifecycleOwner owner);

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy(@NotNull LifecycleOwner owner);

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onLifecycleChanged(@NotNull LifecycleOwner owner,
                            @NotNull Lifecycle.Event event);
}

public class BasePresenter implements IPresenter {
        
    private static final String TAG = "com.qingmei2.module.base.BasePresenter";    

    @Override
    public void onLifecycleChanged(@NotNull LifecycleOwner owner, @NotNull Lifecycle.Event event) {

    }

    @Override
    public void onCreate(@NotNull LifecycleOwner owner) {
        Log.d("tag", "BasePresenter.onCreate" + this.getClass().toString());
    }

    @Override
    public void onDestroy(@NotNull LifecycleOwner owner) {
        Log.d("tag", "BasePresenter.onDestroy" + this.getClass().toString());
    }
}

這里我直接將我想要觀察到Presenter的生命周期事件都列了出來,然后封裝到BasePresenter 中,這樣每一個BasePresenter 的子類都能感知到Activity容器對應的生命周期事件,并在子類重寫的方法中,對應相應行為。

2、在Activity/Fragment容器中添加Observer:

public class MainActivity extends AppCompatActivity {
    private IPresenter mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("tag", "onCreate" + this.getClass().toString());
        setContentView(R.layout.activity_main);
        mPresenter = new MainPresenter(this);
        getLifecycle().addObserver(mPresenter);//添加LifecycleObserver
    }

    @Override
    protected void onDestroy() {
        Log.d("tag", "onDestroy" + this.getClass().toString());
        super.onDestroy();
    }
}

如此,每當Activity發生了對應的生命周期改變,Presenter就會執行對應事件注解的方法:

除onCreate和onDestroy事件之外,Lifecycle一共提供了所有的生命周期事件,只要
通過注解進行聲明,就能夠使LifecycleObserver觀察到對應的生命周期事件:

//以下為logcat日志
01-08 23:21:01.702  D/tag: onCreate  class com.qingmei2.mvparchitecture.mvp.ui.MainActivity
01-08 23:21:01.778  D/tag: onCreate  class com.qingmei2.mvparchitecture.mvp.presenter.MainPresenter

01-08 23:21:21.074  D/tag: onDestroy  class com.qingmei2.mvparchitecture.mvp.presenter.MainPresenter
01-08 23:21:21.074  D/tag: onDestroy  class com.qingmei2.mvparchitecture.mvp.ui.MainActivity
 public enum Event {
        /**
         * Constant for onCreate event of the {@link LifecycleOwner}.
         */
        ON_CREATE,
        /**
         * Constant for onStart event of the {@link LifecycleOwner}.
         */
        ON_START,
        /**
         * Constant for onResume event of the {@link LifecycleOwner}.
         */
        ON_RESUME,
        /**
         * Constant for onPause event of the {@link LifecycleOwner}.
         */
        ON_PAUSE,
        /**
         * Constant for onStop event of the {@link LifecycleOwner}.
         */
        ON_STOP,
        /**
         * Constant for onDestroy event of the {@link LifecycleOwner}.
         */
        ON_DESTROY,
        /**
         * An {@link Event Event} constant that can be used to match all events.
         */
        ON_ANY
    }

二、原理分析

先說結論:

借鑒Android 架構組件(一)——Lifecycle, @ShymanZhu的一張圖進行簡單的概括:

Lifecycle組件原理

我們先將重要的這些類挑選出來:

  • LifecycleObserver接口( Lifecycle觀察者):實現該接口的類,通過注解的方式,可以通過被LifecycleOwner類的addObserver(LifecycleObserver o)方法注冊,被注冊后,LifecycleObserver便可以觀察到LifecycleOwner的生命周期事件

  • LifecycleOwner接口(Lifecycle持有者):實現該接口的類持有生命周期(Lifecycle對象),該接口的生命周期(Lifecycle對象)的改變會被其注冊的觀察者LifecycleObserver觀察到并觸發其對應的事件。

  • Lifecycle(生命周期):和LifecycleOwner不同的是,LifecycleOwner本身持有Lifecycle對象,LifecycleOwner通過其Lifecycle getLifecycle()的接口獲取內部Lifecycle對象。

  • State(當前生命周期所處狀態):如圖所示。

  • Event(當前生命周期改變對應的事件):如圖所示,當Lifecycle發生改變,如進入onCreate,會自動發出ON_CREATE事件。

了解了這些類和接口的職責,接下來原理分析就簡單很多了,我們以Fragment為例,來看下實際Fragment等類和上述類或接口的聯系:

1、Fragment:LifecycleOwner

  • Fragment(Activity同理,我們 本文以Fragment為例,下同):實現了LifecycleOwner接口,這意味著Fragment對象持有生命周期對象(Lifecycle),并可以通過Lifecycle getLifecycle()方法獲取內部的Lifecycle對象:
public class Fragment implements xxx, LifecycleOwner {
    
    //...省略其他

   LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

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

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}

可以看到,實現的getLifecycle()方法,實際上返回的是 LifecycleRegistry 對象,LifecycleRegistry對象實際上繼承了 Lifecycle,這個下文再講。

持有Lifecycle有什么作用呢?實際上在Fragment對應的生命周期內,都會發送對應的生命周期事件給內部的 LifecycleRegistry對象處理:

public class Fragment implements xxx, LifecycleOwner {
    //...
    void performCreate(Bundle savedInstanceState) {
        onCreate(savedInstanceState);  //1.先執行生命周期方法
        //...省略代碼
        //2.生命周期事件分發
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }

    void performStart() {
        onStart();
        //...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

    void performResume() {
         onResume();
        //...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }

    void performPause() {
        //3.注意,調用順序變了
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        //...
        onPause();
    }

    void performStop() {
       mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
        //...
        onStop();
    }

    void performDestroy() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        //...
        onDestroy();
    }
}

隨著Fragment不同走到不同的生命周期,除了暴露給我們的生命周期方法onCreate/onStart/..../onDestroy等,同時,Fragment內部的Lifecycle對象(就是mLifecycleRegistry)還將生命周期對應的事件作為參數傳給了 handleLifecycleEvent() 方法。

同時,你會發現Fragment中performCreate()、performStart()、performResume()會先調用自身的onXXX()方法,然后再調用LifecycleRegistry的handleLifecycleEvent()方法;而在performPause()、performStop()、performDestroy()中會先LifecycleRegistry的handleLifecycleEvent()方法 ,然后調用自身的onXXX()方法。

參照Android 架構組件(一)——Lifecycle, @ShymanZhu文中的時序圖:

Lifecycle 在Fragment中的時序圖

我們從圖中可以看到,當Fragment將生命周期對應的事件交給其內部的Lifecycle處理后, LifecycleObserver (就是我們上文自定義的Presenter),就能夠接收到對應的生命周期事件,這是如何實現的呢?

2、LifecycleRegistry:Lifecycle

首先確認一點,LifecycleRegistry 就是 Lifecycle 的子類:

public class LifecycleRegistry extends Lifecycle {
}

我們看一下 Lifecycle

public abstract class Lifecycle {

        //注冊LifecycleObserver (比如Presenter)
        public abstract void addObserver(@NonNull LifecycleObserver observer);
        //移除LifecycleObserver 
        public abstract void removeObserver(@NonNull LifecycleObserver observer);
        //獲取當前狀態
        public abstract State getCurrentState();

        public enum Event {
            ON_CREATE,
            ON_START,
            ON_RESUME,
            ON_PAUSE,
            ON_STOP,
            ON_DESTROY,
            ON_ANY
        }
        
       public enum State {
            DESTROYED,
            INITIALIZED,
            CREATED,
            STARTED,
            RESUMED;

            public boolean isAtLeast(@NonNull State state) {
                return compareTo(state) >= 0;
            }
       }
}

Lifecycle沒什么要講的,幾個抽象方法也能看懂,作為Lifecycle的子類,LifecycleRegistry 同樣也能通過addObserver方法注冊LifecycleObserver (就是Presenter),當LifecycleRegistry 本身的生命周期改變后(可以想象,內部一定有一個成員變量State記錄當前的生命周期),LifecycleRegistry 就會逐個通知每一個注冊的LifecycleObserver ,并執行對應生命周期的方法。

我們看一下LifecycleRegistry 的handleLifecycleEvent()方法:

    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

看方法的名字我們就可以知道,handleLifecycleEvent方法會通過 getStateAfter 獲取當前應處的狀態并修改 Lifecycle本身的State 值,緊接著遍歷所 LifecycleObserver 并同步且通知其狀態發生變化,因此就能觸發LifecycleObserver 對應的生命周期事件。

實際上LifecycleRegistry 本身還是有很多值得一提之處,本文只闡述清楚原理,暫不涉及源碼詳解。

一些小Tips

1、嘗試復用LifecycleRegistry

首先,LifecycleRegistry 本身就是一個成熟的 Lifecycle 實現類,它被實例化在Activity和Fragment中使用,如果我們需要自定義LifecycleOwner 并實現接口需要返回一個Lifecycle實例,完全可以直接在自定義LifecycleOwner中new一個LifecycleRegistry成員并返回它(簡而言之就是:直接拿來用即可)。

以下是Google官方文檔:

LifecycleRegistry: An implementation of Lifecycle that can handle multiple observers. It is used by Fragments and Support Library Activities. You can also directly use it if you have a custom LifecycleOwner.

2、注解和DefaultLifecycleObserver的取舍

其次,Google的Lifecycle庫中提供了一個 DefaultLifecycleObserver 類,方便我們直接實現LifecycleObserver接口,相比較于文中demo所使用的注解方式,Google官方更推薦我們使用 DefaultLifecycleObserver 類,并聲明

一旦Java 8成為Android的主流,注釋將被棄用,所以介于DefaultLifecycleObserver和注解兩者之間,更推薦使用 DefaultLifecycleObserver

官方原文:

/*
 * If you use <b>Java 8 Language</b>, then observe events with {@link DefaultLifecycleObserver}.
 * To include it you should add {@code "android.arch.lifecycle:common-java8:<version>"} to your
 * build.gradle file.
 * <pre>
 * class TestObserver implements DefaultLifecycleObserver {
 *     {@literal @}Override
 *     public void onCreate(LifecycleOwner owner) {
 *         // your code
 *     }
 * }
 * </pre>
 * If you use <b>Java 7 Language</b>, Lifecycle events are observed using annotations.
 * Once Java 8 Language becomes mainstream on Android, annotations will be deprecated, so between
 * {@link DefaultLifecycleObserver} and annotations,
 * you must always prefer {@code DefaultLifecycleObserver}.
 */

* 3、Lifecycles 的最佳實踐

本小節內容節選自《[譯] Architecture Components 之 Handling Lifecycles》
作者:zly394
鏈接:https://juejin.im/post/5937e1c8570c35005b7b262a

  • 保持 UI 控制器(Activity 和 Fragment)盡可能的精簡。它們不應該試圖去獲取它們所需的數據;相反,要用 ViewModel來獲取,并且觀察 LiveData將數據變化反映到視圖中。

  • 嘗試編寫數據驅動(data-driven)的 UI,即 UI 控制器的責任是在數據改變時更新視圖或者將用戶的操作通知給 ViewModel。

  • 將數據邏輯放到 ViewModel 類中。ViewModel 應該作為 UI 控制器和應用程序其它部分的連接服務。注意:不是由 ViewModel 負責獲取數據(例如:從網絡獲取)。相反,ViewModel 調用相應的組件獲取數據,然后將數據獲取結果提供給 UI 控制器。

  • 使用Data Binding來保持視圖和 UI 控制器之間的接口干凈。這樣可以讓視圖更具聲明性,并且盡可能減少在 Activity 和 Fragment 中編寫更新代碼。如果你喜歡在 Java 中執行該操作,請使用像Butter Knife 這樣的庫來避免使用樣板代碼并進行更好的抽象化。

  • 如果 UI 很復雜,可以考慮創建一個 Presenter 類來處理 UI 的修改。雖然通常這樣做不是必要的,但可能會讓 UI 更容易測試。

  • 不要在 ViewModel 中引用View或者 Activity的 context。因為如果ViewModel存活的比 Activity 時間長(在配置更改的情況下),Activity 將會被泄漏并且無法被正確的回收。

總結

總而言之,Lifecycle還是有可取之處的,相對于其它架構組件之間的配合,Lifecycle更簡單且獨立(實際上配合其他組件味道更佳)。

本文旨在分析Lifecycle框架相關類的原理,將不會對Lifecycle每一行的源碼進行深入地探究,如果有機會,筆者將嘗試寫一篇源碼詳細解析。

參考&感謝

Lifecycle-aware Components 源碼分析 @chaosleong

Android 架構組件(一)——Lifecycle @ShymanZhu

--------------------------廣告分割線------------------------------

系列文章

爭取打造 Android Jetpack 講解的最好的博客系列

Android Jetpack 實戰篇


關于我

Hello,我是卻把清梅嗅,如果您覺得文章對您有價值,歡迎 ??,也歡迎關注我的個人博客或者Github

如果您覺得文章還差了那么點東西,也請通過關注督促我寫出更好的文章——萬一哪天我進步了呢?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容