系列文章導(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持久化庫
原文地址:https://developer.android.com/topic/libraries/architecture/lifecycle.html
android.arch.lifecycle 包提供了類和接口允許你構(gòu)建生命周期感知(lifecycle-aware)的組件——可以基于當(dāng)前activity或fragment生命周期自動調(diào)節(jié)它們的行為的組件堂鲤。
注意:將 android.arch.lifecycle 導(dǎo)入Android工程逮光,請參見將Architecture Components引入工程。
大部分定義在Android框架中的組件都包含附加到其上的生命周期。這些生命周期由操作系統(tǒng)或運(yùn)行在你的進(jìn)程中的框架代碼管理盯串。它們是Android如何工作的核心,你的應(yīng)用程序必須尊重它們。不這樣做可能會觸發(fā)內(nèi)存泄漏甚至應(yīng)用程序崩潰。
假設(shè)在屏幕上我們有一個(gè)展示設(shè)備位置的activity熏瞄。一個(gè)常見的實(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è)例子看起來不錯(cuò),在一個(gè)真正的應(yīng)用中谬以,你最終會遇到太多像這樣的調(diào)用巴刻,然后onStart()
和onStop()
方法會變得非常大。
此外蛉签,一些組件不能剛剛在onStart()
中啟動胡陪。如果我們需要在啟動位置觀察之前檢查一些配置怎么辦?有可能某些情況檢查是在activity已經(jīng)停止之后才結(jié)束碍舍,這意味著myLocationListener.start()
的調(diào)用是在myLocationListener.stop()
調(diào)用之后柠座,基本上就會一直保持連接了。
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包提供了類和接口片橡,幫助你以靈活和隔離的方式解決這些問題妈经。
Lifecycle
Lifecycle類保存有組件(如activity或fragment)的生命周期狀態(tài)信息,并允許其他對象觀察此狀態(tài)捧书。
Lifecycle
使用兩個(gè)主要的枚舉來跟蹤其相關(guān)組件的生命周期狀態(tài)吹泡。
Event
從框架和Lifecycle類分派的生命周期事件。這些事件映射到activity和fragment的回調(diào)事件经瓷。
State
由Lifecycle對象跟蹤的組件的當(dāng)前狀態(tài)
將狀態(tài)視作圖的結(jié)點(diǎn)爆哑,事件看作這些結(jié)點(diǎn)之間的邊。
一個(gè)類可以通過給方法添加注解來觀察組件的生命周期舆吮。
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è)單一方法接口揭朝,表示該類擁有一個(gè)Lifecycle。它的唯一方法getLifecycle()
必須被這個(gè)類實(shí)現(xiàn)色冀。
此類從單獨(dú)的類(比如activity和fragment)里抽象了Lifecycle
的所有權(quán)潭袱,并允許編寫與兩者兼容的組件。任何自定義應(yīng)用程序類可以實(shí)現(xiàn)LifecycleOwner
接口锋恬。
注意:由于
Architecture Components
還處于Alpha階段屯换,Fragment
和AppCompatActivity
類不能實(shí)現(xiàn)它(因?yàn)槲覀儾荒軓囊粋€(gè)穩(wěn)定的組件中添加一個(gè)依賴,導(dǎo)致其變成不穩(wěn)定的API)与学。在Lifecycle
穩(wěn)定之前彤悔,為了方便,提供了LifecycleActivity
和LifecycleFragment
類癣防。在Lifecycle
工程發(fā)布后蜗巧,支持庫的fragment和activity將會實(shí)現(xiàn)LifecycleOwner
接口掌眠。到時(shí)將不推薦使用LifecycleActivity
和LifecycleFragment
蕾盯。另請參閱在自定義activity和fragment中實(shí)現(xiàn)LifecycleOwner。
對于上面的例子,我們可以讓MyLocationListener類成為LifecycleObserver级遭,然后在onCreate中使用我們的Lifecycle初始化它望拖。這允許MyLocationListener
類是自足的,意味著它可以在必要的時(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è)常見的用例是说敏,避免在Lifecycle處于不良狀態(tài)時(shí)調(diào)用某些回調(diào)。例如丢郊,如果回調(diào)在activity狀態(tài)保存后運(yùn)行一個(gè)fragment事務(wù)盔沫,則會觸發(fā)崩潰,因此我們永遠(yuǎn)不會想要調(diào)用那個(gè)回調(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
}
}
通過這個(gè)實(shí)現(xiàn)干茉,我們的LocationListener
類是完全生命周期感知的了谴忧。它可以自行初始化和清理,而不受activity的管理角虫。如果我們需要從另一個(gè)Activity或Fragment使用它沾谓,我們只需要初始化它。所有的安裝和拆卸操作都由類本身管理戳鹅。
可以與Lifecycle
一起使用的類被稱為生命周期感知組件均驶。鼓勵(lì)那些提供需要使用Android生命周期的類的庫提供生命周期感知組件,以便客戶端可以輕松繼承這些類枫虏,而無需在客戶端手動進(jìn)行生命周期管理辣恋。
LiveData
是生命周期感知組件的示例。與ViewModel
一起使用LiveData
模软,可以在遵循Android生命周期的情況下伟骨,更容易使用數(shù)據(jù)填充UI。
Lifecycle最佳實(shí)踐
- 保持UI控制器(activity和fragment)盡可能瘦燃异。它們不應(yīng)該視圖獲取自己的數(shù)據(jù)携狭,而是使用ViewModel來做,并觀察LiveData以將更改反映到View中回俐。
- 嘗試別寫數(shù)據(jù)驅(qū)動的UI逛腿,你的UI控制器負(fù)責(zé)在數(shù)據(jù)更改時(shí)更新View,而不是將用戶操作通知回ViewModel仅颇。
- 把你的數(shù)據(jù)邏輯放到ViewModel類中单默。ViewModel應(yīng)該扮演你的UI控制器和應(yīng)用其余部分之間的連接器。但是請注意忘瓦,不是ViewModel的責(zé)任來拉取數(shù)據(jù)(比如搁廓,從網(wǎng)絡(luò))。相反,ViewModel應(yīng)該調(diào)用相應(yīng)的組件來做這個(gè)事兒境蜕,然后把結(jié)果返回給UI控制器蝙场。
- 使用Data Binding來保持view和UI控制器之間干凈的接口。這可以讓你的視圖更具聲明性粱年,并最大限度減少你需要在activity和fragment之間編寫的更新代碼售滤。如果你更喜歡Java中這么做,使用像ButterKnife這樣的庫來避免模板代碼台诗,并進(jìn)行更好的抽象完箩。
- 如果你的UI很復(fù)雜,考慮創(chuàng)建一個(gè)Presenter類來處理UI修改拉队。這通常是過度的嗜憔,但可能讓你的UI更容易測試。
- 永遠(yuǎn)不要在
ViewModel
中引用view
或activity context
氏仗。如果ViewModel
的生命周期超過activity(比如更改配置的情況)吉捶,activity將會泄漏,無法正確地被垃圾回收皆尔。
附錄
自定義的activity和fragment實(shí)現(xiàn)LifecycleOwer
任何自定義的activity和fragment可以通過實(shí)現(xiàn)內(nèi)置的LifecycleRegistryOwner
接口(而不是擴(kuò)展LifecycleFragment
或LifecycleActivity
)來轉(zhuǎn)換成LifecycleOwner
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
如果你想把一個(gè)自定義類轉(zhuǎn)換成LifecycleOwner
呐舔,你可以使用LifecycleRegistry
類,但是你需要把事件轉(zhuǎn)發(fā)給這個(gè)類慷蠕。對于實(shí)現(xiàn)了LifecycleRegistryOwner
的activity和fragment來說珊拼,轉(zhuǎn)換將會自動完成。