官方文檔鏈接:https://developer.android.google.cn/topic/libraries/architecture/lifecycle.html
1.前言
上一篇文章大體介紹了框架的層級和優(yōu)勢,接下來的幾篇將詳細(xì)介紹各個特性。首先來了解一下組件生命周期的管理,以及如何將業(yè)務(wù)與生命周期相關(guān)聯(lián)。
2.使用案例
android.arch.lifecycle包提供了類和接口,以便實現(xiàn)生命周期感知組件,能自動根據(jù)當(dāng)前Activity和Fragment的狀態(tài)調(diào)整行為。
假設(shè)一個場景,通過一個Activity在屏幕上顯示設(shè)備當(dāng)前的位置。下面是最常見的寫法:
class MyLocationListener {
public MyLocationListener(Context context, Callback callback) {
// ...
}
void start() {
// connect to system location service
}
void stop() {
// disconnect from system location service
}
}
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> {
// update UI
});
}
public void onStart() {
super.onStart();
myLocationListener.start();
}
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
雖然這個例子看起來不錯,但在實際項目中,會有大量的類似需求,導(dǎo)致onStart()和onStop()方法變得很臃腫。此外,有些組件無法直接在onStart()方法中啟動,比如在啟動定位服務(wù)前需檢查一些配置。某些情況下,Activity已經(jīng)停止了,檢查才結(jié)束,意味著 myLocationListener.stop()調(diào)用之后才調(diào)用myLocationListener.start()方法。
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// update UI
});
}
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start();
}
});
}
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
3.Lifecycle類
Lifecycle是一個類,持有組件(Activity和Fragment)生命周期狀態(tài)的信息,并允許其它對象觀察狀態(tài)。主要由以下兩個部分組成:
- Event:這些事件與Activity和Fragment的系統(tǒng)回調(diào)一一對應(yīng)。
- State:組件的當(dāng)前狀態(tài)由Lifecycle對象管理。

State是圖形中的一個個節(jié)點,而Event則是節(jié)點之間的線。點可以存在很長或很短時間,線象征著變化的過程。通過給一個類的方法添加注釋來管理相應(yīng)組件的生命周期狀態(tài)。
public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
}
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());
4.LifecycleOwner類
LifecycleOwner是擁有單一方法getLifecycle()的接口,表示實現(xiàn)類有一個Lifecycle。通過它獲取到組件(Activity,F(xiàn)ragment)的Lifecycle,從而能讓其它的組件一起工作。自定義的Application可以實現(xiàn)此接口以提供生命周期。
由于架構(gòu)組件還處于alpha階段,不能將不穩(wěn)定的API引入到穩(wěn)定的代碼中,所以Fragment和AppCompatActivity類未能實現(xiàn)此接口。在Lifecycle穩(wěn)定前,可以使用LifecycleActivity和LifecycleFragment代替。等正式版發(fā)布后,支持庫中的Activity和Fragment將會實現(xiàn)LifecycleOwner接口,而LifecycleActivity和LifecycleFragment也將同時廢棄。
上面的例子,可以讓MyLocationListener類實現(xiàn)LifecycleObserver接口,并在組件onCreate()方法中通過Lifecycle初始化。這樣它就能自己管理,必要時還能清理自己。
class MyActivity extends LifecycleActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
// update UI
});
Util.checkUserStatus(result -> {
if (result) {
myLocationListener.enable();
}
});
}
}
當(dāng)Lifecycle不在一個好的狀態(tài)時,有些回調(diào)通常是不能調(diào)用的。例如,當(dāng)Activity的狀態(tài)是銷毀的,若在回調(diào)中執(zhí)行Fragment事務(wù),將會導(dǎo)致crash,所以此時不希望啟用回調(diào)。
為了讓實例簡單,Lifecycle類允許其它的對象查詢當(dāng)前狀態(tài)。
class MyLocationListener implements LifecycleObserver {
private boolean enabled = false;
public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start() {
if (enabled) {
// connect
}
}
public void enable() {
enabled = true;
if (lifecycle.getState().isAtLeast(STARTED)) {
// connect if not connected
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop() {
// disconnect if connected
}
}
這樣實現(xiàn)后,MyLocationListener類已可以感知生命周期了,不需要在Activity中管理初始化和釋放了。如果另一個Activity或Fragment需要使用此類,僅僅需要初始化它,所有的安裝和拆卸操作由它自己管理。
LiveData就是生命周期感知組件,與ViewModel一起使用,可以在遵守生命周期下更容易地為界面提供數(shù)據(jù)。
5.最佳實踐
- 保持UI Controller(Activity和Fragment)代碼盡可能少。它們不應(yīng)該自己存儲數(shù)據(jù);相反,應(yīng)由ViewModel提供,并觀察LiveData以便將變化反映到視圖上。
- 嘗試數(shù)據(jù)驅(qū)動界面,UI Controller負(fù)責(zé)數(shù)據(jù)變化時更新界面,或者將用戶操作反饋給ViewModel。
- ViewModel類中放入數(shù)據(jù)邏輯,作為UI Controller和應(yīng)用其它部分的連接。不過需注意,獲取數(shù)據(jù)不是它的職責(zé)(例如,網(wǎng)絡(luò)請求);相反,應(yīng)該調(diào)用相關(guān)組件來做,再將結(jié)果返回給UI Controller。
- 使用Data Binding在View和UI Controller之間保持干凈的接口。這將使View的功能清楚且省去Activity和Fragment中更新界面的代碼。如果喜歡在代碼中完成,可以使用Butter Knife庫來避免樣板代碼和獲得更好的抽象。
- 如果界面過于復(fù)雜,可創(chuàng)建Presenter類處理界面的修改行為。通常沒必要,但是可以使界面更容易測試。
- 不要在ViewModel中引用View或Activity的上下文。因為它的生命周期較長(比如配置改變時),導(dǎo)致View或Activity泄露,無法被垃圾回收。
6.自定義實現(xiàn)LifecycleOwner
支持庫版本26.1.0之后,Activity和Fragment已經(jīng)實現(xiàn)LifecycleOwner。如果自定義一個類實現(xiàn)LifecycleOwner,需要讓它持有LifecycleRegistry對象,并調(diào)用handleLifecycleEvent(Lifecycle.Event event)方法分發(fā)事件。
LifecycleRegistry的使用,可以參考別人翻譯的老版文檔,如下:
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
7.總結(jié)
將業(yè)務(wù)行為放到Activity和Fragment等組件中,無非就是方便獲取界面交互事件和生命周期。MVP架構(gòu)中將業(yè)務(wù)行為放到Presenter中,通過View層去調(diào)用,而現(xiàn)在創(chuàng)建多個類來監(jiān)聽生命周期,并在其中實現(xiàn)各自業(yè)務(wù)的邏輯,使結(jié)構(gòu)更加清晰,避免Presenter過于龐大。