系列文章
【背上Jetpack】Jetpack 主要組件的依賴及傳遞關(guān)系
【背上Jetpack】AdroidX下使用Activity和Fragment的變化
【背上Jetpack之Fragment】你真的會用Fragment嗎?Fragment常見問題以及androidx下Fragment的使用新姿勢
【背上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 中有一個比較重要的概念:「生命周期」笼裳。剛畢業(yè)去面試,總會被問到「四大組件的生命周期」這類的問題佛舱。17年的 IO 大會上诸尽,Google 推出了 Lifecycle-Aware Components(生命周期感知組件)原杂,幫助開發(fā)者組織更好,更輕量弦讽,易于維護(hù)的代碼
本文介紹 Lifecycle
的職責(zé)以及簡單分析 lifecycle 如何感知 activity 和 fragment 污尉,幫助您對 Lifecycle
有一個感性的認(rèn)識
萬物基于 Lifecycle
手動管理生命周期的痛苦你不懂
魯迅曾說過:萬物基于 Lifecycle
哦不對
Android 中的視圖控制器就有這么多生命周期的情況,所以處理好生命周期十分重要往产,否則會導(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 生命周期的組件
}
}
此示例看起來不錯,在實際的應(yīng)用程序中仿村,您仍然會響應(yīng)生命周期的當(dāng)前狀態(tài)而進(jìn)行過多的調(diào)用來管理 UI 和其他組件锐朴。 管理多個組件會在生命周期方法中放置大量代碼,例如 onStart() 和 onStop()蔼囊,這使它們難以維護(hù)
而且焚志,不能保證組件在 activity 或 fragment 停止之前就已啟動。 如果我們需要執(zhí)行長時間運行的操作(例如onStart() 中的某些配置檢查)畏鼓,則可能會導(dǎo)致爭用情況酱酬,其中onStop() 方法在 onStart() 之前完成,從而使組件的生存期超過了所需的生存期云矫。
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)的時機釋放資源挑社,并且在錯過生命周期時能及時叫停異步的任務(wù)就好了,
我們不妨先思考一下巡揍,如果實現(xiàn)這樣的想法痛阻,應(yīng)該如何做
按照慣例的思考
首先我們先來整理一下我們的需求
- 內(nèi)部組件能夠感知外部的生命周期
- 能夠統(tǒng)一地管理,做到一處修改腮敌,處處生效
- 能夠及時叫停錯過的任務(wù)
針對需求1阱当,可以用觀察者模式,內(nèi)部組件能夠在外部生命周期變化時做出相應(yīng)
針對需求2糜工,可以將依賴組件的代碼移出生命周期方法內(nèi)斗这,然后移入組件本身,這樣只需修改組件內(nèi)部邏輯即可
針對需求3啤斗,可以在合適的時機移除觀察者
觀察者模式
關(guān)于開發(fā)者模式,我第一次比較詳細(xì)的了解是在 扔物線 的 給 Android 開發(fā)者的 RxJava 詳解赁咙。
觀察者模式面向的需求是:A 對象(觀察者)對 B 對象(被觀察者)的某種變化高度敏感钮莲,需要在 B 變化的一瞬間做出反應(yīng)荧止。舉個例子怔鳖,新聞里喜聞樂見的警察抓小偷,警察需要在小偷伸手作案的時候?qū)嵤┳ゲ丁T谶@個例子里杏愤,警察是觀察者,小偷是被觀察者蒲凶,警察需要時刻盯著小偷的一舉一動熟妓,才能保證不會漏過任何瞬間。程序的觀察者模式和這種真正的『觀察』略有不同慈俯,觀察者不需要時刻盯著被觀察者(例如 A 不需要每過 2ms 就檢查一次 B 的狀態(tài))渤刃,而是采用注冊(Register)或者稱為訂閱(Subscribe)的方式,告訴被觀察者:我需要你的某某狀態(tài)贴膘,你要在它變化的時候通知我卖子。 Android 開發(fā)中一個比較典型的例子是點擊監(jiān)聽器
OnClickListener
。對設(shè)置OnClickListener
來說刑峡,View
是被觀察者洋闽,OnClickListener
是觀察者,二者通過setOnClickListener()
方法達(dá)成訂閱關(guān)系突梦。訂閱之后用戶點擊按鈕的瞬間诫舅,Android Framework 就會將點擊事件發(fā)送給已經(jīng)注冊的OnClickListener
。采取這樣被動的觀察方式宫患,既省去了反復(fù)檢索狀態(tài)的資源消耗刊懈,也能夠得到最高的反饋速度。當(dāng)然撮奏,這也得益于我們可以隨意定制自己程序中的觀察者和被觀察者俏讹,而警察叔叔明顯無法要求小偷『你在作案的時候務(wù)必通知我』。
OnClickListener 的模式大致如下圖:
上述描述及圖片均來自 給 Android 開發(fā)者的 RxJava 詳解
因此在生命周期組件的生命周期發(fā)生變化時告訴觀察者畜吊,內(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)
這是 Lifecycle 的結(jié)構(gòu)泽疆,抽象類,其內(nèi)部有兩個枚舉玲献,分別代表著「事件」和「狀態(tài)」殉疼,此外還有三個方法,添加/移除觀察者捌年,獲取當(dāng)前狀態(tài)
注意瓢娜,這里 State 中的枚舉順序是有意義的,后文詳細(xì)介紹
其實現(xiàn)類為 LifecycleRegistry 礼预,可以處理多個觀察者
其內(nèi)部持有當(dāng)前的狀態(tài) mState 眠砾,LifecycleOwner 以及觀察者的自定義列表,同時重寫了父類的添加/刪除觀察者的方法
LifecycleOwner 托酸,具有 Android 的生命周期褒颈,定制組件可以使用這些事件來處理生命周期更改柒巫,而無需在 Activity 或 Fragment 中實現(xiàn)任何代碼
LifecycleObserver ,將一個類標(biāo)記為 LifecycleObserver
谷丸。 它沒有任何方法堡掏,而是依賴于 OnLifecycleEvent 注解的方法
LifecycleEventObserver ,可以接收任何生命周期更改并將其分派給接收方刨疼。
如果一個類實現(xiàn)此接口并同時使用 OnLifecycleEvent泉唁,則注解將被忽略
DefaultLifecycleObserver ,用于監(jiān)聽 LifecycleOwner 狀態(tài)更改的回調(diào)接口揩慕。
如果一個類同時實現(xiàn)了此接口和 LifecycleEventObserver亭畜,則將首先調(diào)用DefaultLifecycleObserver
的方法,然后再調(diào)用LifecycleEventObserver.onStateChanged(LifecycleOwner漩绵,Lifecycle.Event)
注意:使用 DefaultLifecycleObserver 需引入
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
簡單的源碼分析
activity 生命周期處理
首先我們還是來看 androidx.activity.ComponentActivity 贱案,這個類我們這個系列的文章里提到多次,第一次提及是在 【背上Jetpack】絕不丟失的狀態(tài) androidx SaveState ViewModel-SaveState 分析 止吐,感興趣的小伙伴可以看看宝踪。
其實現(xiàn)的接口大多數(shù)我們都已經(jīng)探討過了,今天我們來看看 LifecycleOwner
ActivityResultCaller 為 activity 1.2.0-alpha02 推出的碍扔,旨在統(tǒng)一 onActivityResult 瘩燥,這里暫時不討論它
既然實現(xiàn)了 LifecycleOwner
接口,必定重寫 getLifecycle() 方法
// androidx.activity.ComponentActivity.java
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
其返回的 Lifecycle
為 實現(xiàn)類 LifecycleRegistry
的實例
而 activity 操作生命周期是通過 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 及以上 直接注冊正確的生命周期回調(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();
}
}
// 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è)備上直接注冊正確的生命周期回調(diào)二拐,低版本通過啟動 ReportFragment 服鹅,借助 fragment 各個生命周期來處理生命周期回調(diào)
fragment 生命周期處理
在 fragment 內(nèi)部,每個生命周期節(jié)點調(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
中有一個 isAtLeast
方法百新,用于判斷當(dāng)前狀態(tài)是否不小于傳入的狀態(tài)
// Lifecycle.State
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
枚舉的 compareTo 方法其實是比較的枚舉聲明的順序
而 State 的順序為 DESTROYED -> INITIALIZED -> CREATED -> STARTED -> RESUMED
如果傳入的 state 為 STARTED企软,則當(dāng)前狀態(tài)為 STARTED 或 RESUMED 時返回 true ,否則返回 false
LiveData 篇會用到這個知識點
關(guān)于我
我是 Fly_with24