系列文章導航:
- 【譯】Google官方推出的Android架構組件系列文章(一)App架構指南
- 【譯】Google官方推出的Android架構組件系列文章(二)將Architecture Components引入工程
- 【譯】Google官方推出的Android架構組件系列文章(三)處理生命周期
- 【譯】Google官方推出的Android架構組件系列文章(四)LiveData
- 【譯】Google官方推出的Android架構組件系列文章(五)ViewModel
- 【譯】Google官方推出的Android架構組件系列文章(六)Room持久化庫
原文地址:https://developer.android.com/topic/libraries/architecture/lifecycle.html
android.arch.lifecycle 包提供了類和接口允許你構建生命周期感知(lifecycle-aware)的組件——可以基于當前activity或fragment生命周期自動調節它們的行為的組件。
注意:將 android.arch.lifecycle 導入Android工程,請參見將Architecture Components引入工程。
大部分定義在Android框架中的組件都包含附加到其上的生命周期。這些生命周期由操作系統或運行在你的進程中的框架代碼管理。它們是Android如何工作的核心,你的應用程序必須尊重它們。不這樣做可能會觸發內存泄漏甚至應用程序崩潰。
假設在屏幕上我們有一個展示設備位置的activity。一個常見的實現可能像下面這樣:
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();
}
}
即使這個例子看起來不錯,在一個真正的應用中,你最終會遇到太多像這樣的調用,然后onStart()
和onStop()
方法會變得非常大。
此外,一些組件不能剛剛在onStart()
中啟動。如果我們需要在啟動位置觀察之前檢查一些配置怎么辦?有可能某些情況檢查是在activity已經停止之后才結束,這意味著myLocationListener.start()
的調用是在myLocationListener.stop()
調用之后,基本上就會一直保持連接了。
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)的生命周期狀態信息,并允許其他對象觀察此狀態。
Lifecycle
使用兩個主要的枚舉來跟蹤其相關組件的生命周期狀態。
Event
從框架和Lifecycle類分派的生命周期事件。這些事件映射到activity和fragment的回調事件。
State
由Lifecycle對象跟蹤的組件的當前狀態
將狀態視作圖的結點,事件看作這些結點之間的邊。
一個類可以通過給方法添加注解來觀察組件的生命周期。
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 是一個單一方法接口,表示該類擁有一個Lifecycle。它的唯一方法getLifecycle()
必須被這個類實現。
此類從單獨的類(比如activity和fragment)里抽象了Lifecycle
的所有權,并允許編寫與兩者兼容的組件。任何自定義應用程序類可以實現LifecycleOwner
接口。
注意:由于
Architecture Components
還處于Alpha階段,Fragment
和AppCompatActivity
類不能實現它(因為我們不能從一個穩定的組件中添加一個依賴,導致其變成不穩定的API)。在Lifecycle
穩定之前,為了方便,提供了LifecycleActivity
和LifecycleFragment
類。在Lifecycle
工程發布后,支持庫的fragment和activity將會實現LifecycleOwner
接口。到時將不推薦使用LifecycleActivity
和LifecycleFragment
。另請參閱在自定義activity和fragment中實現LifecycleOwner。
對于上面的例子,我們可以讓MyLocationListener類成為LifecycleObserver,然后在onCreate中使用我們的Lifecycle初始化它。這允許MyLocationListener
類是自足的,意味著它可以在必要的時候進行自我清理。
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();
}
});
}
}
一個常見的用例是,避免在Lifecycle處于不良狀態時調用某些回調。例如,如果回調在activity狀態保存后運行一個fragment事務,則會觸發崩潰,因此我們永遠不會想要調用那個回調。
為了簡化此用例,Lifecycle類允許其他對象查詢當前狀態。
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
}
}
通過這個實現,我們的LocationListener
類是完全生命周期感知的了。它可以自行初始化和清理,而不受activity的管理。如果我們需要從另一個Activity或Fragment使用它,我們只需要初始化它。所有的安裝和拆卸操作都由類本身管理。
可以與Lifecycle
一起使用的類被稱為生命周期感知組件。鼓勵那些提供需要使用Android生命周期的類的庫提供生命周期感知組件,以便客戶端可以輕松繼承這些類,而無需在客戶端手動進行生命周期管理。
LiveData
是生命周期感知組件的示例。與ViewModel
一起使用LiveData
,可以在遵循Android生命周期的情況下,更容易使用數據填充UI。
Lifecycle最佳實踐
- 保持UI控制器(activity和fragment)盡可能瘦。它們不應該視圖獲取自己的數據,而是使用ViewModel來做,并觀察LiveData以將更改反映到View中。
- 嘗試別寫數據驅動的UI,你的UI控制器負責在數據更改時更新View,而不是將用戶操作通知回ViewModel。
- 把你的數據邏輯放到ViewModel類中。ViewModel應該扮演你的UI控制器和應用其余部分之間的連接器。但是請注意,不是ViewModel的責任來拉取數據(比如,從網絡)。相反,ViewModel應該調用相應的組件來做這個事兒,然后把結果返回給UI控制器。
- 使用Data Binding來保持view和UI控制器之間干凈的接口。這可以讓你的視圖更具聲明性,并最大限度減少你需要在activity和fragment之間編寫的更新代碼。如果你更喜歡Java中這么做,使用像ButterKnife這樣的庫來避免模板代碼,并進行更好的抽象。
- 如果你的UI很復雜,考慮創建一個Presenter類來處理UI修改。這通常是過度的,但可能讓你的UI更容易測試。
- 永遠不要在
ViewModel
中引用view
或activity context
。如果ViewModel
的生命周期超過activity(比如更改配置的情況),activity將會泄漏,無法正確地被垃圾回收。
附錄
自定義的activity和fragment實現LifecycleOwer
任何自定義的activity和fragment可以通過實現內置的LifecycleRegistryOwner
接口(而不是擴展LifecycleFragment
或LifecycleActivity
)來轉換成LifecycleOwner
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
如果你想把一個自定義類轉換成LifecycleOwner
,你可以使用LifecycleRegistry
類,但是你需要把事件轉發給這個類。對于實現了LifecycleRegistryOwner
的activity和fragment來說,轉換將會自動完成。