系列文章導(dǎo)航:
- 【譯】Google官方推出的Android架構(gòu)組件系列文章(一)App架構(gòu)指南
- 【譯】Google官方推出的Android架構(gòu)組件系列文章(二)將Architecture Components引入工程
- 【譯】Google官方推出的Android架構(gòu)組件系列文章(三)處理生命周期
- 【譯】Google官方推出的Android架構(gòu)組件系列文章(四)LiveData
- 【譯】Google官方推出的Android架構(gòu)組件系列文章(五)ViewModel
- 【譯】Google官方推出的Android架構(gòu)組件系列文章(六)Room持久化庫(kù)
原文地址:https://developer.android.com/topic/libraries/architecture/lifecycle.html
android.arch.lifecycle 包提供了類(lèi)和接口允許你構(gòu)建生命周期感知(lifecycle-aware)的組件——可以基于當(dāng)前activity或fragment生命周期自動(dòng)調(diào)節(jié)它們的行為的組件。
注意:將 android.arch.lifecycle 導(dǎo)入Android工程,請(qǐng)參見(jiàn)將Architecture Components引入工程。
大部分定義在Android框架中的組件都包含附加到其上的生命周期。這些生命周期由操作系統(tǒng)或運(yùn)行在你的進(jìn)程中的框架代碼管理。它們是Android如何工作的核心,你的應(yīng)用程序必須尊重它們。不這樣做可能會(huì)觸發(fā)內(nèi)存泄漏甚至應(yīng)用程序崩潰。
假設(shè)在屏幕上我們有一個(gè)展示設(shè)備位置的activity。一個(gè)常見(jiàn)的實(shí)現(xiàn)可能像下面這樣:
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();
}
}
即使這個(gè)例子看起來(lái)不錯(cuò),在一個(gè)真正的應(yīng)用中,你最終會(huì)遇到太多像這樣的調(diào)用,然后onStart()和onStop()方法會(huì)變得非常大。
此外,一些組件不能剛剛在onStart()中啟動(dòng)。如果我們需要在啟動(dòng)位置觀察之前檢查一些配置怎么辦?有可能某些情況檢查是在activity已經(jīng)停止之后才結(jié)束,這意味著myLocationListener.start()的調(diào)用是在myLocationListener.stop()調(diào)用之后,基本上就會(huì)一直保持連接了。
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();
}
}
android.arch.lifecycle包提供了類(lèi)和接口,幫助你以靈活和隔離的方式解決這些問(wèn)題。
Lifecycle
Lifecycle類(lèi)保存有組件(如activity或fragment)的生命周期狀態(tài)信息,并允許其他對(duì)象觀察此狀態(tài)。
Lifecycle使用兩個(gè)主要的枚舉來(lái)跟蹤其相關(guān)組件的生命周期狀態(tài)。
Event
從框架和Lifecycle類(lèi)分派的生命周期事件。這些事件映射到activity和fragment的回調(diào)事件。
State
由Lifecycle對(duì)象跟蹤的組件的當(dāng)前狀態(tài)

將狀態(tài)視作圖的結(jié)點(diǎn),事件看作這些結(jié)點(diǎn)之間的邊。
一個(gè)類(lèi)可以通過(guò)給方法添加注解來(lá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());
LifecycleOwner
LifecycleOwner 是一個(gè)單一方法接口,表示該類(lèi)擁有一個(gè)Lifecycle。它的唯一方法getLifecycle()必須被這個(gè)類(lèi)實(shí)現(xiàn)。
此類(lèi)從單獨(dú)的類(lèi)(比如activity和fragment)里抽象了Lifecycle的所有權(quán),并允許編寫(xiě)與兩者兼容的組件。任何自定義應(yīng)用程序類(lèi)可以實(shí)現(xiàn)LifecycleOwner接口。
注意:由于
Architecture Components還處于Alpha階段,Fragment和AppCompatActivity類(lèi)不能實(shí)現(xiàn)它(因?yàn)槲覀儾荒軓囊粋€(gè)穩(wěn)定的組件中添加一個(gè)依賴(lài),導(dǎo)致其變成不穩(wěn)定的API)。在Lifecycle穩(wěn)定之前,為了方便,提供了LifecycleActivity和LifecycleFragment類(lèi)。在Lifecycle工程發(fā)布后,支持庫(kù)的fragment和activity將會(huì)實(shí)現(xiàn)LifecycleOwner接口。到時(shí)將不推薦使用LifecycleActivity和LifecycleFragment。另請(qǐng)參閱在自定義activity和fragment中實(shí)現(xiàn)LifecycleOwner。
對(duì)于上面的例子,我們可以讓MyLocationListener類(lèi)成為L(zhǎng)ifecycleObserver,然后在onCreate中使用我們的Lifecycle初始化它。這允許MyLocationListener類(lèi)是自足的,意味著它可以在必要的時(shí)候進(jìn)行自我清理。
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();
}
});
}
}
一個(gè)常見(jiàn)的用例是,避免在Lifecycle處于不良狀態(tài)時(shí)調(diào)用某些回調(diào)。例如,如果回調(diào)在activity狀態(tài)保存后運(yùn)行一個(gè)fragment事務(wù),則會(huì)觸發(fā)崩潰,因此我們永遠(yuǎn)不會(huì)想要調(diào)用那個(gè)回調(diào)。
為了簡(jiǎn)化此用例,Lifecycle類(lèi)允許其他對(duì)象查詢(xún)當(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
}
}
通過(guò)這個(gè)實(shí)現(xiàn),我們的LocationListener類(lèi)是完全生命周期感知的了。它可以自行初始化和清理,而不受activity的管理。如果我們需要從另一個(gè)Activity或Fragment使用它,我們只需要初始化它。所有的安裝和拆卸操作都由類(lèi)本身管理。
可以與Lifecycle一起使用的類(lèi)被稱(chēng)為生命周期感知組件。鼓勵(lì)那些提供需要使用Android生命周期的類(lèi)的庫(kù)提供生命周期感知組件,以便客戶(hù)端可以輕松繼承這些類(lèi),而無(wú)需在客戶(hù)端手動(dòng)進(jìn)行生命周期管理。
LiveData是生命周期感知組件的示例。與ViewModel一起使用LiveData,可以在遵循Android生命周期的情況下,更容易使用數(shù)據(jù)填充UI。
Lifecycle最佳實(shí)踐
- 保持UI控制器(activity和fragment)盡可能瘦。它們不應(yīng)該視圖獲取自己的數(shù)據(jù),而是使用ViewModel來(lái)做,并觀察LiveData以將更改反映到View中。
- 嘗試別寫(xiě)數(shù)據(jù)驅(qū)動(dòng)的UI,你的UI控制器負(fù)責(zé)在數(shù)據(jù)更改時(shí)更新View,而不是將用戶(hù)操作通知回ViewModel。
- 把你的數(shù)據(jù)邏輯放到ViewModel類(lèi)中。ViewModel應(yīng)該扮演你的UI控制器和應(yīng)用其余部分之間的連接器。但是請(qǐng)注意,不是ViewModel的責(zé)任來(lái)拉取數(shù)據(jù)(比如,從網(wǎng)絡(luò))。相反,ViewModel應(yīng)該調(diào)用相應(yīng)的組件來(lái)做這個(gè)事兒,然后把結(jié)果返回給UI控制器。
- 使用Data Binding來(lái)保持view和UI控制器之間干凈的接口。這可以讓你的視圖更具聲明性,并最大限度減少你需要在activity和fragment之間編寫(xiě)的更新代碼。如果你更喜歡Java中這么做,使用像ButterKnife這樣的庫(kù)來(lái)避免模板代碼,并進(jìn)行更好的抽象。
- 如果你的UI很復(fù)雜,考慮創(chuàng)建一個(gè)Presenter類(lèi)來(lái)處理UI修改。這通常是過(guò)度的,但可能讓你的UI更容易測(cè)試。
- 永遠(yuǎn)不要在
ViewModel中引用view或activity context。如果ViewModel的生命周期超過(guò)activity(比如更改配置的情況),activity將會(huì)泄漏,無(wú)法正確地被垃圾回收。
附錄
自定義的activity和fragment實(shí)現(xiàn)LifecycleOwer
任何自定義的activity和fragment可以通過(guò)實(shí)現(xiàn)內(nèi)置的LifecycleRegistryOwner接口(而不是擴(kuò)展LifecycleFragment或LifecycleActivity)來(lái)轉(zhuǎn)換成LifecycleOwner
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
如果你想把一個(gè)自定義類(lèi)轉(zhuǎn)換成LifecycleOwner,你可以使用LifecycleRegistry類(lèi),但是你需要把事件轉(zhuǎn)發(fā)給這個(gè)類(lèi)。對(duì)于實(shí)現(xiàn)了LifecycleRegistryOwner的activity和fragment來(lái)說(shuō),轉(zhuǎn)換將會(huì)自動(dòng)完成。