Jetpack Lifecycle 該怎么看?還肝否?

前言

Jetpack AAC 系列文章:

Jetpack Lifecycle 該怎么看?還肝否?
Jetpack LiveData 是時候了解一下了
Jetpack ViewModel 抽絲剝繭

前面幾篇文章都是為了Jetpack 打基礎,本篇從Lifecycle開始將正式進入Jetpack 各個組件的分析。
通過本篇文章你將了解到:

1、為什么需要Lifecycle?
2、Lifecycle 如何使用?
3、Lifecycle 如何感知生命周期
4、Lifecycle 內存泄漏?
5、總結

1、為什么需要Lifecycle?

生命周期的起始

Android 中常見的擁有生命周期的組件如Activity、Fragment、Service等,其中Activity、Fragment最為常見,而Fragment的生命周期依托于Activity,因此掌握了Activity的生命周期,其它不在話下。
Activity 生命周期跌宕起伏的故事,請移步:
Android Activity 生命周期詳解及監聽

生命周期的運用

青銅選手

舉個簡單的例子:當進入Activity 時(獲取焦點)需要網絡請求,當Activity 退出時(失去焦點)停止網絡請求,最簡單的做法如下:

    @Override
    protected void onResume() {
        super.onResume();
        NetRequest.startRequest();
    }

    @Override
    protected void onPause() {
        super.onPause();
        NetRequest.stopRequest();
    }

重寫onResume()方法,當該方法被調用時,說明Activity獲取了焦點,頁面即將展示,此時可以進行網絡請求拉取數據。
重寫onPause()方法,當該方法被調用時,說明Activity 失去了焦點,此時沒必要再請求網絡了。
看似沒啥問題,但仔細想想:比如在播放視頻的時候,也需要在onResume()方法里播放,在onPause()方法里暫停,再比如數據庫操作等,這個時候onResume()、onPause()里就疊放了許多代碼,使得Activity 變得很臃腫。

白銀選手

你說沒關系,我有MVP 架構,可以用Presenter 來封裝這些業務邏輯。
聲明Presenter類:LifecyclePresenter

public class LifecyclePresenter implements ILifecycle{
    @Override
    public void onResume() {
        NetRequest.startRequest();
    }

    @Override
    public void onPause() {
        NetRequest.stopRequest();
    }
}

該類實現了接口:ILifecycle,而此接口聲明的方法與Activity 生命周期契合:

interface ILifecycle {
    void onCreate();
    void onStart();
    void onResume();
    void onPause();
    void onStop();
    void onDestroy();
}

好了,最后在Activity 里監聽生命周期的變化,進而調用LifecyclePresenter 不同方法:

    @Override
    protected void onResume() {
        super.onResume();
        lifecyclePresenter.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        lifecyclePresenter.onPause();
    }

如此一來,以后有其它的業務邏輯,只需要在LifecyclePresenter 對應的方法里添加即可,達成了給Activity 減負的效果。

黃金選手

雖然Activity 生命周期各個方法里只新增了一行代碼,但是考慮到UI 和邏輯的分離,最好是兩者不產生耦合。比如在分工的時候,有些同學負責UI,那么他可能就不會關心什么時候開始/結束網絡請求,這些由負責具體業務邏輯的同學來編寫。該怎么來實現呢?
還記得在分析Activity生命周期時有說過:
Activity 提供了registerActivityLifecycleCallbacks(callback)方法,當Activity生命周期發生變動時就會調用該方法。因此咱們可以在此監聽生命周期的變動,然后調用相應的業務代碼:

public class LifecycleHelper {
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public static void bindLifecycle(Activity activity, ILifecycle iLifecycle) {
        if (activity == null)
            return;
        activity.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityResumed(@NonNull Activity activity) {
                if (iLifecycle != null)
                    iLifecycle.onResume();
            }

            @Override
            public void onActivityPaused(@NonNull Activity activity) {
                if (iLifecycle != null)
                    iLifecycle.onPause();
            }
        });
    }
}

傳入的Activity 即為想要監聽生命周期的Activity。

public class LifecyclePresenterV2 {
    @RequiresApi(api = Build.VERSION_CODES.Q)
    public LifecyclePresenterV2(Activity activity) {
        LifecycleHelper.bindLifecycle(activity, new ILifecycle() {
            @Override
            public void onResume() {
                NetRequest.startRequest();
            }

            @Override
            public void onPause() {
                NetRequest.stopRequest();
            }
        });
    }
}

改造Presenter為:LifecyclePresenterV2。
此時,Activity 里只需要調用:

  //this 表示當前需要監聽的Activity
  LifecyclePresenterV2 lifecyclePresenterV2 = new LifecyclePresenterV2(this);

可以看出:

Activity 里無需再重寫各個生命周期的回調方法,僅僅只需要一行代碼,即可將這些邏輯放到單獨的業務層處理,生命周期和具體業務綁定,看業務的需求想怎么和生命周期聯動就怎么來。
后續若是換了Activity,那么邏輯層的業務也無需變動。

似乎萬事大吉了?非也,仔細看registerActivityLifecycleCallbacks()方法調用有版本限制:@RequiresApi(api = Build.VERSION_CODES.Q)
意思就是該API 必須是Android 10(29)以上才能調用,這局限性可大了。

Lifecycle 的引入

從上面的分析我們可以感知到,生命周期和業務的聯動場景挺豐富的,也著實需要一套工具來幫助我們簡化聯動過程。

Google說要有Lifecycle,于是便有了Lifecycle。

開宗明義:Lifecycle 源碼并不復雜,主要就是做了三件事:

1、提供給外界監聽感興趣的生命周期里的某個階段(onResume、onPause、onDestroy等)的接口,外界此時化身為觀察者。
2、在某個地方監聽Activity生命周期,此時Activity為被觀察者。
3、將生命周期告知給觀察者。

2、Lifecycle 如何使用?

添加觀察者

從Lifecycle 三件事可知,外界想要監聽生命周期變化,僅僅只需要添加觀察接口,在接口的回調方法里處理對應生命周期即可。
有兩種不同的方式:

1、注解方式處理觀察結果

Lifecycle 以前的版本為了少重寫接口里的方法,使用了注解來簡化觀察者。

    //注解的實現方式
    class MyObserver7 implements LifecycleObserver {
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        void onPause() {
            Log.d(TAG, "onPause");
        }
    }

此處只關注onPause,若是還想監測其它狀態變化,只需要添加對應狀態的注解即可。
而后在Activity 里監聽:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lifecycle);

        getLifecycle().addObserver(new MyObserver7());
    }

當Activity 失去焦點后就會調用MyObserver7里的onPause()方法。
可以看出,在Activity里只需要添加觀察者即可。

2、接口方式處理觀察結果

Lifecycle 新版本廢棄了注解觀察方式,使用了接口來代替,若是你使用了Java8或者開啟了Java8 特性,建議使用接口方式。

    //Java8 方式
    class MyObserver8 implements DefaultLifecycleObserver {
        @Override
        public void onPause(LifecycleOwner owner) {
            Log.d(TAG, "pause");
        }
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lifecycle);
        getLifecycle().addObserver(new MyObserver8());
    }

可以看出,實現了DefaultLifecycleObserver 接口,該接口繼承了FullLifecycleObserver 接口。

interface FullLifecycleObserver extends LifecycleObserver {
    void onCreate(LifecycleOwner owner);
    void onStart(LifecycleOwner owner);
    void onResume(LifecycleOwner owner);
    void onPause(LifecycleOwner owner);
    void onStop(LifecycleOwner owner);
    void onDestroy(LifecycleOwner owner);
}

而DefaultLifecycleObserver 接口默認實現了FullLifecycleObserver全部的方法

    @Override
    default void onCreate(@NonNull LifecycleOwner owner) {
    }
    ....

可以看出使用了Java8 的新特性:default 修飾接口方法。
因此當我們實現了DefaultLifecycleObserver接口時,僅僅只需要重寫關注的狀態對應的接口即可。

3、Lifecycle 如何感知生命周期

綜上所述,通過Lifecycle 可以很方便地感知Activity生命周期的變化,前面部分咱們也是一步步分析該怎么封裝生命周期,很遺憾遇到了registerActivityLifecycleCallbacks 版本限制的問題,接下來探究Lifecycle究竟是怎么做到繞開限制的。

第一步:注冊觀察者

LifecycleRegistry

不管是接口還是注解方式都使用了getLifecycle(),該方法返回Lifecycle 對象,而Lifecycle是抽象類,getLifecycle()返回的是Lifecycle 的子類:LifecycleRegistry 的對象。

#ComponentActivity.java
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

當自定義的Activity 繼承自AppCompatActivity時,而ComponentActivity 是AppCompatActivity 的父類,因此自定義的Activity 調用getLifecycle()時返回的即是mLifecycleRegistry 對象。
而LifecycleRegistry里的mLifecycleOwner對象即是自定義的Activity 本身(弱引用)。

addObserver()

#LifecycleRegistry.java
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        Lifecycle.State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //傳入observer,構造ObserverWithState
        LifecycleRegistry.ObserverWithState statefulObserver = new LifecycleRegistry.ObserverWithState(observer, initialState);
        //將ObserverWithState 加入到map 里
        LifecycleRegistry.ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        ...
    }

關鍵之處在于ObserverWithState:

#LifecycleRegistry.java
    static class ObserverWithState {
        //生命周期狀態
        Lifecycle.State mState;
        //觀察者
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, Lifecycle.State initialState) {
            //封裝觀察者
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Lifecycle.Event event) {
            //分發事件,將event轉為state
            Lifecycle.State newState = event.getTargetState();
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

再看Lifecycling.lifecycleEventObserver:

#Lifecycling.java
    static LifecycleEventObserver lifecycleEventObserver(Object object) {
        //接口方式
        boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
        ...
        if (isFullLifecycleObserver) {
            //如果觀察者是接口方式,直接返回
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
        }

        //處理注解,將注解記錄下來,下次直接從map里取
        final Class<?> klass = object.getClass();
        int type = getObserverConstructorType(klass);
        ...
        return new ReflectiveGenericLifecycleObserver(object);
    }

addObserver()的重點是將Observer經過一些列封裝后添加到Map里。

明顯地我們會想到:當生命周期變更后,將會從Map里取出觀察者,并通知它。

第二步:生命周期變更-通知觀察者

Android10(含) 以上處理方式

了解Lifecycle 如何通知觀察者,最好的方法莫過于通過斷點查看其調用堆棧。
以接口處理方式為例,當觀察者被調用時,其調用棧如下:


image.png

注意到Activity. dispatchActivityPostStarted()方法:

#Activity.java
    private void dispatchActivityPostStarted() {
        //找到監聽者
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                //調用回調方法
                ((Application.ActivityLifecycleCallbacks) callbacks[i])
                        .onActivityPostStarted(this);
            }
        }
        ...
    }

而此處的監聽者即為通過Activity.registerActivityLifecycleCallbacks(callback)注冊的。
而callback 即為:ReportFragment.LifecycleCallbacks 對象,該對象的注冊在:

#ReportFragment.java
    public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            //如果是Android10以上,則直接注冊ActivityLifecycleCallbacks
            ReportFragment.LifecycleCallbacks.registerIn(activity);
        }
        //將一個空的Fragment添加到Activity里
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            // Hopefully, we are the first to make a transaction.
            manager.executePendingTransactions();
        }
    }

而injectIfNeededIn的調用時機是在Activity.onCreate()里。
好了,現在我們已經了解了:

在Activity 創建時,通過ReportFragment 監聽Activity 狀態變化。

而ReportFragment 依據系統版本的不同,分兩種監聽方式:

1、在Android 10以上(含)的設備是通過registerActivityLifecycleCallbacks()監聽的。
2、在Android 10以下是通過Fragment 監聽的。

行文至此,Lifecycle僅僅只是監聽了Activity 的狀態,還需要將狀態分發下去。
還是以Android10處理方式為例:

#ReportFragment.java
    static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
        ...
        if (activity instanceof LifecycleOwner) {
            //獲取Lifecycle,也即是LifecycleRegistry
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                //分發事件
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

最終事件還是交由LifecycleRegistry 處理,而LifecycleRegistry 里依據Event和State 轉換,最后從Map 里找到對應的封裝Observer,最終通知Activity里注冊的observer,至此就完成了一次生命周期狀態變化的通知。

Android 10以下處理方式

我們知道,當Fragment關聯上Activity時,那么它的生命周期就與Activity 聯動了。具體請移步:Android Fragment 要你何用?

因此當Activity 生命周期變化時,會調用Fragment某個方法,以onStart()狀態為例:

#ReportFragment.java
    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        //分發事件
        dispatch(Lifecycle.Event.ON_START);
    }

    private void dispatch(@NonNull Lifecycle.Event event) {
        if (Build.VERSION.SDK_INT < 29) {
            //Android 10 以下才處理
            dispatch(getActivity(), event);
        }
    }

此時,我們知道了Lifecycle 如何處理registerActivityLifecycleCallbacks()版本限制問題:即是通過ReportFragment 對上層調用者屏蔽監聽Activity生命周期變化的細節。在Android 10(含)以上使用registerActivityLifecycleCallbacks(),在其之下使用空的Fragment 添加到Activity。

Lifecycle 感知生命周期總結

用圖表示如下:


image.png

綠色部分:

Lifecycle 監聽Activity生命周期變化。

藍色部分:

外界通過Lifecycle 注冊觀察者。

紅色部分:

Lifecycle 監聽到生命周期發生變化,通知觀察者。

4、Lifecycle 內存泄漏?

在Activity(假設自定義為LifeActivity) onCreate()里添加如下代碼,監測Activity 生命周期:

        getLifecycle().addObserver(new DefaultLifecycleObserver() {
            @Override
            public void onCreate(@NonNull @org.jetbrains.annotations.NotNull LifecycleOwner owner) {
                
            }
        });

問題來了:是否需要在Activity.onDestroy()里移除觀察者呢?
我們知道,匿名內部類持有外部類引用,addObserver(xx),這個xx 對象持有了Activity,通常來說看到這樣的寫法我們立馬就關聯到了:若是xx沒有被釋放,那么當Activity 銷毀時,Activity 對象是無法被釋放的,因為它被xx持有。
因此大部分時候我們需要在Activity.onDestroy() 里removeObserver(xx)。

接著來看看getLifecycle().addObserver(xx)此種情況是否需要主動移除observer。問題的關鍵是xx被誰持有了。
通過前面的分析可知,xx 被封裝為ObserverWithState 對象,最后存儲到Map里。而這個Map為:

#LifecycleRegistry.java
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();

它是LifecycleRegistry 的成員變量,而LifecycleRegistry 對象是ComponentActivity 的成員變量,最終結果:Map 是LifeActivity 的成員變量。
當Activity 銷毀時,Map將會被銷毀,而Map 將不會再持有Observer。
因此,得出的結論是:

無需調用getLifecycle().removeObserver(observer);

內存泄漏的本質是:長生命周期的對象持有短生命周期對象的引用,導致短生命周期對象無法釋放。

5、總結

本篇文章并沒有將側重點放在Lifecycle.State 與Lifecycle.Event 之間的轉換,而是著眼于為什么需要Lifecycle以及Lifecycle 如何感知生命周期,希望能夠自然而然地引入Lifecycle,并了解其設計原理。
Lifecycle 是LiveData的基礎,接下來將會分析LiveData的妙用。

本文基于:implementation 'androidx.appcompat:appcompat:1.4.1'

Lifecycle 源碼測試

您若喜歡,請點贊、關注,您的鼓勵是我前進的動力

持續更新中,和我一起步步為營系統、深入學習Android

1、Android各種Context的前世今生
2、Android DecorView 必知必會
3、Window/WindowManager 不可不知之事
4、View Measure/Layout/Draw 真明白了
5、Android事件分發全套服務
6、Android invalidate/postInvalidate/requestLayout 徹底厘清
7、Android Window 如何確定大小/onMeasure()多次執行原因
8、Android事件驅動Handler-Message-Looper解析
9、Android 鍵盤一招搞定
10、Android 各種坐標徹底明了
11、Android Activity/Window/View 的background
12、Android Activity創建到View的顯示過
13、Android IPC 系列
14、Android 存儲系列
15、Java 并發系列不再疑惑
16、Java 線程池系列
17、Android Jetpack 前置基礎系列
18、Android Jetpack 易懂易學系列

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容