【背上Jetpack之Lifecycle】萬(wàn)物基于 Lifecycle 默默無(wú)聞大用處

系列文章

【背上Jetpack】Jetpack 主要組件的依賴及傳遞關(guān)系

【背上Jetpack】AdroidX下使用Activity和Fragment的變化

【背上Jetpack之Fragment】你真的會(huì)用Fragment嗎?Fragment常見問(wèn)題以及androidx下Fragment的使用新姿勢(shì)

【背上Jetpack之Fragment】從源碼角度看 Fragment 生命周期 AndroidX Fragment1.2.2源碼分析

【背上Jetpack之OnBackPressedDispatcher】Fragment 返回棧預(yù)備篇

【背上Jetpack之Fragment】從源碼的角度看Fragment 返回棧 附多返回棧demo

【背上Jetpack】絕不丟失的狀態(tài) androidx SaveState ViewModel-SaveState 分析

【背上Jetpack之ViewModel】即使您不使用MVVM也要了解ViewModel ——ViewModel 的職能邊界

目錄

前言

Android 中有一個(gè)比較重要的概念:「生命周期」。剛畢業(yè)去面試,總會(huì)被問(wèn)到「四大組件的生命周期」這類的問(wèn)題。17年的 IO 大會(huì)上,Google 推出了 Lifecycle-Aware Components(生命周期感知組件),幫助開發(fā)者組織更好,更輕量,易于維護(hù)的代碼

本文介紹 Lifecycle 的職責(zé)以及簡(jiǎn)單分析 lifecycle 如何感知 activity 和 fragment ,幫助您對(duì) Lifecycle 有一個(gè)感性的認(rèn)識(shí)

萬(wàn)物基于 Lifecycle

手動(dòng)管理生命周期的痛苦你不懂

lifecycles

魯迅曾說(shuō)過(guò):萬(wàn)物基于 Lifecycle

image

哦不對(duì)

image

Android 中的視圖控制器就有這么多生命周期的情況,所以處理好生命周期十分重要,否則會(huì)導(dǎo)致內(nèi)存泄漏甚至是程序崩潰。這里引用 官方文檔 的例子

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // 連接系統(tǒng)的定位服務(wù)
    }

    void stop() {
        // 與系統(tǒng)的定位服務(wù)斷開連接
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    @Override
    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // 更新 UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        myLocationListener.start();
        //管理其他需要響應(yīng) activity 生命周期的組件
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
        //管理其他需要響應(yīng) activity 生命周期的組件
    }
}

此示例看起來(lái)不錯(cuò),在實(shí)際的應(yīng)用程序中,您仍然會(huì)響應(yīng)生命周期的當(dāng)前狀態(tài)而進(jìn)行過(guò)多的調(diào)用來(lái)管理 UI 和其他組件。 管理多個(gè)組件會(huì)在生命周期方法中放置大量代碼,例如 onStart() 和 onStop(),這使它們難以維護(hù)

而且,不能保證組件在 activity 或 fragment 停止之前就已啟動(dòng)。 如果我們需要執(zhí)行長(zhǎng)時(shí)間運(yùn)行的操作(例如onStart() 中的某些配置檢查),則可能會(huì)導(dǎo)致爭(zhēng)用情況,其中onStop() 方法在 onStart() 之前完成,從而使組件的生存期超過(guò)了所需的生存期。

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, location -> {
            // 更新 UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // 如果在 activity 停止后調(diào)用此回調(diào)怎么辦?
            if (result) {
                myLocationListener.start();
            }
        });
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

如果有所有的組件,都能感知外部的生命周期,能在相應(yīng)的時(shí)機(jī)釋放資源,并且在錯(cuò)過(guò)生命周期時(shí)能及時(shí)叫停異步的任務(wù)就好了,

image

我們不妨先思考一下,如果實(shí)現(xiàn)這樣的想法,應(yīng)該如何做

按照慣例的思考

首先我們先來(lái)整理一下我們的需求

  • 內(nèi)部組件能夠感知外部的生命周期
  • 能夠統(tǒng)一地管理,做到一處修改,處處生效
  • 能夠及時(shí)叫停錯(cuò)過(guò)的任務(wù)

針對(duì)需求1,可以用觀察者模式,內(nèi)部組件能夠在外部生命周期變化時(shí)做出相應(yīng)

針對(duì)需求2,可以將依賴組件的代碼移出生命周期方法內(nèi),然后移入組件本身,這樣只需修改組件內(nèi)部邏輯即可

針對(duì)需求3,可以在合適的時(shí)機(jī)移除觀察者

觀察者模式

關(guān)于開發(fā)者模式,我第一次比較詳細(xì)的了解是在 扔物線給 Android 開發(fā)者的 RxJava 詳解。

觀察者模式面向的需求是:A 對(duì)象(觀察者)對(duì) B 對(duì)象(被觀察者)的某種變化高度敏感,需要在 B 變化的一瞬間做出反應(yīng)。舉個(gè)例子,新聞里喜聞樂(lè)見的警察抓小偷,警察需要在小偷伸手作案的時(shí)候?qū)嵤┳ゲ?。在這個(gè)例子里,警察是觀察者,小偷是被觀察者,警察需要時(shí)刻盯著小偷的一舉一動(dòng),才能保證不會(huì)漏過(guò)任何瞬間。程序的觀察者模式和這種真正的『觀察』略有不同,觀察者不需要時(shí)刻盯著被觀察者(例如 A 不需要每過(guò) 2ms 就檢查一次 B 的狀態(tài)),而是采用注冊(cè)(Register)或者稱為訂閱(Subscribe)的方式,告訴被觀察者:我需要你的某某狀態(tài),你要在它變化的時(shí)候通知我。 Android 開發(fā)中一個(gè)比較典型的例子是點(diǎn)擊監(jiān)聽器 OnClickListener 。對(duì)設(shè)置 OnClickListener 來(lái)說(shuō), View 是被觀察者, OnClickListener 是觀察者,二者通過(guò) setOnClickListener() 方法達(dá)成訂閱關(guān)系。訂閱之后用戶點(diǎn)擊按鈕的瞬間,Android Framework 就會(huì)將點(diǎn)擊事件發(fā)送給已經(jīng)注冊(cè)的 OnClickListener 。采取這樣被動(dòng)的觀察方式,既省去了反復(fù)檢索狀態(tài)的資源消耗,也能夠得到最高的反饋速度。當(dāng)然,這也得益于我們可以隨意定制自己程序中的觀察者和被觀察者,而警察叔叔明顯無(wú)法要求小偷『你在作案的時(shí)候務(wù)必通知我』。

OnClickListener 的模式大致如下圖:

image

上述描述及圖片均來(lái)自 給 Android 開發(fā)者的 RxJava 詳解

因此在生命周期組件的生命周期發(fā)生變化時(shí)告訴觀察者,內(nèi)部組件即可感知外部的生命周期

引入 Lifecycle 后

public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());

源碼結(jié)構(gòu)

image

這是 Lifecycle 的結(jié)構(gòu),抽象類,其內(nèi)部有兩個(gè)枚舉,分別代表著「事件」和「狀態(tài)」,此外還有三個(gè)方法,添加/移除觀察者,獲取當(dāng)前狀態(tài)

注意,這里 State 中的枚舉順序是有意義的,后文詳細(xì)介紹

其實(shí)現(xiàn)類為 LifecycleRegistry ,可以處理多個(gè)觀察者

LifecycleRegistry

其內(nèi)部持有當(dāng)前的狀態(tài) mState ,LifecycleOwner 以及觀察者的自定義列表,同時(shí)重寫了父類的添加/刪除觀察者的方法

LifecycleOwner

LifecycleOwner ,具有 Android 的生命周期,定制組件可以使用這些事件來(lái)處理生命周期更改,而無(wú)需在 Activity 或 Fragment 中實(shí)現(xiàn)任何代碼

LifecycleObserver ,將一個(gè)類標(biāo)記為 LifecycleObserver。 它沒(méi)有任何方法,而是依賴于 OnLifecycleEvent 注解的方法

LifecycleEventObserver ,可以接收任何生命周期更改并將其分派給接收方。

如果一個(gè)類實(shí)現(xiàn)此接口并同時(shí)使用 OnLifecycleEvent,則注解將被忽略

DefaultLifecycleObserver ,用于監(jiān)聽 LifecycleOwner 狀態(tài)更改的回調(diào)接口。

如果一個(gè)類同時(shí)實(shí)現(xiàn)了此接口和 LifecycleEventObserver,則將首先調(diào)用DefaultLifecycleObserver 的方法,然后再調(diào)用LifecycleEventObserver.onStateChanged(LifecycleOwner,Lifecycle.Event)

注意:使用 DefaultLifecycleObserver 需引入

implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"

簡(jiǎn)單的源碼分析

activity 生命周期處理

首先我們還是來(lái)看 androidx.activity.ComponentActivity ,這個(gè)類我們這個(gè)系列的文章里提到多次,第一次提及是在 【背上Jetpack】絕不丟失的狀態(tài) androidx SaveState ViewModel-SaveState 分析 ,感興趣的小伙伴可以看看。

ComponentActivity

其實(shí)現(xiàn)的接口大多數(shù)我們都已經(jīng)探討過(guò)了,今天我們來(lái)看看 LifecycleOwner

ActivityResultCaller 為 activity 1.2.0-alpha02 推出的,旨在統(tǒng)一 onActivityResult ,這里暫時(shí)不討論它

image

既然實(shí)現(xiàn)了 LifecycleOwner 接口,必定重寫 getLifecycle() 方法

// androidx.activity.ComponentActivity.java
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

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

其返回的 Lifecycle 為 實(shí)現(xiàn)類 LifecycleRegistry 的實(shí)例

而 activity 操作生命周期是通過(guò) ReportFragment 處理的

// androidx.activity.ComponentActivity.java
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ReportFragment.injectIfNeededIn(this);
    //...
}

// ReportFragment
public static void injectIfNeededIn(Activity activity) {
    if (Build.VERSION.SDK_INT >= 29) {
        // api 29 及以上 直接注冊(cè)正確的生命周期回調(diào)
        activity.registerActivityLifecycleCallbacks(
                new LifecycleCallbacks());
    }
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        manager.executePendingTransactions();
    }
}
image
// ReportFragment.java
static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
    if (activity instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
        return;
    }
    if (activity instanceof LifecycleOwner) {
        Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
        }
    }
}

private void dispatch(@NonNull Lifecycle.Event event) {
    if (Build.VERSION.SDK_INT < 29) {
        dispatch(getActivity(), event);
    }
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    dispatch(Lifecycle.Event.ON_CREATE);
}
@Override
public void onStart() {
    super.onStart();
    dispatch(Lifecycle.Event.ON_START);
}
@Override
public void onResume() {
    super.onResume();
    dispatch(Lifecycle.Event.ON_RESUME);
}
@Override
public void onPause() {
    super.onPause();
    dispatch(Lifecycle.Event.ON_PAUSE);
}
@Override
public void onStop() {
    super.onStop();
    dispatch(Lifecycle.Event.ON_STOP);
}
@Override
public void onDestroy() {
    super.onDestroy();
    dispatch(Lifecycle.Event.ON_DESTROY);
}
// LifecycleCallbacks
static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
    @Override
    public void onActivityPostCreated(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState) {
        dispatch(activity, Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onActivityPostStarted(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_START);
    }

    @Override
    public void onActivityPostResumed(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_RESUME);
    }
    @Override
    public void onActivityPrePaused(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onActivityPreStopped(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onActivityPreDestroyed(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_DESTROY);
    }
    //...
}

在 activity 的 onCreate 方法中,調(diào)用了 ReportFragment 中的靜態(tài)方法 injectIfNeededIn() 。而其內(nèi)部,如果 api 29 及以上的設(shè)備上直接注冊(cè)正確的生命周期回調(diào),低版本通過(guò)啟動(dòng) ReportFragment ,借助 fragment 各個(gè)生命周期來(lái)處理生命周期回調(diào)

fragment 生命周期處理

在 fragment 內(nèi)部,每個(gè)生命周期節(jié)點(diǎn)調(diào)用 handleLifecycleEvent 方法

// Fragment.java
public Fragment() {
    initLifecycle();
}

private void initLifecycle() {
    mLifecycleRegistry = new LifecycleRegistry(this);
}

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

void performCreate(Bundle savedInstanceState) {
    onCreate(savedInstanceState);
    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() {
    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();
}

Lifecycle State 大小比較

Lifecycle.State 中有一個(gè) isAtLeast 方法,用于判斷當(dāng)前狀態(tài)是否不小于傳入的狀態(tài)

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

枚舉的 compareTo 方法其實(shí)是比較的枚舉聲明的順序

而 State 的順序?yàn)?DESTROYED -> INITIALIZED -> CREATED -> STARTED -> RESUMED

如果傳入的 state 為 STARTED,則當(dāng)前狀態(tài)為 STARTED 或 RESUMED 時(shí)返回 true ,否則返回 false

LiveData 篇會(huì)用到這個(gè)知識(shí)點(diǎn)


關(guān)于我


我是 Fly_with24

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容