本文是對lifecycles原文的學(xué)習(xí)和翻譯。也會加入一些自己的體會。如果你有足夠的耐心,就會發(fā)現(xiàn)其實沒接觸之前再難的東西,當(dāng)你花足夠的時間去了解它,你會發(fā)現(xiàn)沒有什么能難倒你 。附上原文地址:Handling lifecycles with lifecycle-aware components | Android Developers
使用生命周期感知組件來處理生命周期
根據(jù)文章標(biāo)題來看,我們對android各大組件的生命周期都不陌生,但是這里有一個新的概念——生命周期感知組件。這里說白了,就是有這樣一個組件如果實現(xiàn)了android.arch.lifecycle提供的接口就能感知如activity/fragment這樣的組件的生命周期,當(dāng)在開發(fā)中某個類要依賴生命周期操作就可以這樣處理。
感知生命周期的組件可以執(zhí)行某個動作,以響應(yīng)其他組件(activity/fragmrnt)的生命周期狀態(tài)的變化。這些組件有助于產(chǎn)生更好的組織性和更輕量的代碼,也更易于維護。
現(xiàn)在的開發(fā)中,有一種常見的業(yè)務(wù)需求。比如某一個業(yè)務(wù)邏輯,要在activity/fragment的某個生命周期中來完成,這樣的方式很容易導(dǎo)致代碼的錯誤擴大化以及影響代碼可讀性。通過使用生命周期感知組件,可以將依賴組件生命周期的代碼從生命周期方法中移出來,這樣就減少了某些風(fēng)險,增加代碼可讀性。
android.arch.lifecycle提供的類和接口可以讓你構(gòu)建能感知生命周期(lifecycle-aware)的類。所謂可以感知生命周期就是能夠感知Activity或者Fragment的生命周期并且可以自行調(diào)整類的行為。
那么在我們工程中怎樣來依賴呢,根據(jù)自己的需要可以選擇你想用的庫。
dependencies {
def lifecycle_version = "1.1.1"
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
// alternatively - just ViewModel
implementation "android.arch.lifecycle:viewmodel:$lifecycle_version"
// use -ktx for Kotlin
// alternatively - just LiveData
implementation "android.arch.lifecycle:livedata:$lifecycle_version"
// alternatively - Lifecycles only (no ViewModel or LiveData).
// Support library depends on this lightweight import
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
// use kapt for Kotlin
// alternately - if using Java8, use the following instead of compiler
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
// optional - ReactiveStreams support for LiveData
implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"
// optional - Test helpers for LiveData
testImplementation "android.arch.core:core-testing:$lifecycle_version"
}
這樣看起來比較麻煩吧,如果你僅僅是需要 Lifecycle,LiveData ,ViewModel只需要這樣進行依賴。
dependencies {
def lifecycle_version = "1.1.1"
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
}
當(dāng)然這么強大的庫,肯定是支持kotlin的,kotlin的引用只需要在版本號之前加上-ktx,如下:
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
在Android框架中定義的大多數(shù)應(yīng)用程序組件都有生命周期。生命周期是由操作系統(tǒng)或運行在你的進程中的框架代為管理的。它們是Android工作的核心,你的應(yīng)用程序必須遵循它們。不這樣做可能觸發(fā)內(nèi)存泄漏或甚至應(yīng)用崩潰。
假如現(xiàn)在我們有一個需求,需要在屏幕上顯示你的位置。一個常見的實現(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;
@Override
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -{
// update UI
});
}
@Override
public void onStart() {
super.onStart();
myLocationListener.start();
// manage other components that need to respond
// to the activity lifecycle
}
@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
// manage other components that need to respond
// to the activity lifecycle
}
}
盡管這個示例看起來不錯,但是在真正的應(yīng)用程序中,你最終會在activity的生命周期中有太多的調(diào)用,這些調(diào)用管理著UI的顯示和其他組件。管理多個組件時會在生命周期方法中放置大量代碼,例如onStart()和onStop(),這使得它們難以維護。
此外,不能保證你的需求代碼在activity或fragment停止之前啟動或者執(zhí)行完畢。如果需要執(zhí)行長時間運行的操作,例如onStart()中的某些配置檢查,則尤其如此。這可能會導(dǎo)致onStop()方法在onStart()之前完成,從而使組件比需要的時間更長,或者出現(xiàn)嚴(yán)重錯誤,因為這種本來就是不符合生命周期規(guī)律的。
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// update UI
});
}
@Override
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// 如果activity結(jié)束了,這個方法才被調(diào)用,怎么辦?
if (result) {
myLocationListener.start();
}
});
}
@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
生命周期包android.arch.lifecycle
提供類和接口,幫助你以更彈性更獨離的方式解決這些問題。
Lifecycle
Lifecycle
是一個保存了關(guān)于組件(如activity或fragment)的生命周期狀態(tài)信息的類,并允許其他對象觀察該狀態(tài)。
Lifecycle使用兩個主要枚舉來跟蹤其相關(guān)組件的生命周期狀態(tài):
Event
從Lifecycle這個框架和Lifecycle類中分發(fā)的生命周期事件。這些事件映射到activity和fragment中的對應(yīng)生命周期事件中。也就是當(dāng)activity的生命周期被Lifecycle觀察,Lifecycle中對應(yīng)的生命周期能通過映射拿到activity當(dāng)前的狀態(tài)。
State
由Lifecycle對象跟蹤的組件(activity / fragment)的當(dāng)前生命周期狀態(tài)。也就是我們能通過Lifecycle拿到activity/fragment當(dāng)前的生命周期。

當(dāng)然這張圖我們不用關(guān)心,因為看起來不直觀啊。我們來直接看看源碼中是什么樣子。
public enum Event {
/**
* Constant for onCreate event of the {@link LifecycleOwner}.
*/
ON_CREATE,
/**
* Constant for onStart event of the {@link LifecycleOwner}.
*/
ON_START,
/**
* Constant for onResume event of the {@link LifecycleOwner}.
*/
ON_RESUME,
/**
* Constant for onPause event of the {@link LifecycleOwner}.
*/
ON_PAUSE,
/**
* Constant for onStop event of the {@link LifecycleOwner}.
*/
ON_STOP,
/**
* Constant for onDestroy event of the {@link LifecycleOwner}.
*/
ON_DESTROY,
/**
* An {@link Event Event} constant that can be used to match all events.
*/
ON_ANY
}
/**
* Lifecycle states. You can consider the states as the nodes in a graph and
* {@link Event}s as the edges between these nodes.
*/
@SuppressWarnings("WeakerAccess")
public enum State {
/**
* Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
* any more events. For instance, for an {@link android.app.Activity}, this state is reached
* <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.
*/
DESTROYED,
/**
* Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is
* the state when it is constructed but has not received
* {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.
*/
INITIALIZED,
/**
* Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
* <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call.
* </ul>
*/
CREATED,
/**
* Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {@link android.app.Activity#onStart() onStart} call;
* <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.
* </ul>
*/
STARTED,
/**
* Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state
* is reached after {@link android.app.Activity#onResume() onResume} is called.
*/
RESUMED;
/**
* Compares if this State is greater or equal to the given {@code state}.
*
* @param state State to compare with
* @return true if this State is greater or equal to the given {@code state}
*/
那我們就來看看具體的使用:
一個類可以通過向其方法添加注釋來監(jiān)視組件的生命周期狀態(tài)。然后通過調(diào)用Lifecycle類的addObserver()方法添加觀察者,如下面的示例所示:
//通過實現(xiàn)LifecycleObserver,我們就能在自己的類中觀察其他組件的生命周期
public class StudyLifecycle implements LifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate(){
Logg.i("onCreate");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart(){
Logg.i("onStart");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume(){
Logg.i("onResume");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause(){
Logg.i("onPause");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop(){
Logg.i("onStop");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy(){
Logg.i("onDestroy");
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//在這里添加我們的觀察者
getLifecycle().addObserver(new StudyLifecycle());
}
}
通過這個例子可以發(fā)現(xiàn),實際上我們擁有生命周期的組件(activity等)實際上是被作為了被觀察者,而Lifecycle作為了觀察者。這樣通過push的方式,我們就能輕松的了解到組件的周期變化。
LifecycleOwner
LifecycleOwner是有單一方法的接口,實現(xiàn)它表示該類具有生命周期。它有一個方法,getLifecycle(),而且是必須由實現(xiàn)的。
這個接口從單獨的類(如fragment和AppCompatActivity)抽象出生命周期的所有權(quán),并允許編寫與之一起工作的組件。任何自定義應(yīng)用程序類都可以實現(xiàn)LifecycleOwner接口。
實現(xiàn)LifecycleObserver的組件與實現(xiàn)LifecycleOwner的組件無縫地工作。這樣你就能看出來實際上我們這這里用的就是觀察者模式,實現(xiàn)了LifecycleOwner接口的類作為被觀察者,實現(xiàn)了LifecycleObserver接口的類作為觀察者。
對于位置跟蹤示例,我們可以使MyLocationListener類實現(xiàn)LifecycleObserver,然后在onCreate()方法中使用activity的Lifecycle初始化它。這允許MyLocationListener類自給自足,這意味著對生命周期狀態(tài)的更改作出反應(yīng)的邏輯是在MyLocationListener中完成的,而不是在activity中完成。讓各個組件存儲它們自己的邏輯使activity和fragment邏輯更易于管理。
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
// update UI
});
Util.checkUserStatus(result -> {
if (result) {
myLocationListener.enable();
}
});
}
}
這里有一個問題就是,例如當(dāng)前的activity在onSaveInstanceState方法執(zhí)行之后在調(diào)用其它回調(diào),則會觸發(fā)崩潰,因此我們永遠不會希望調(diào)用該回調(diào)。
為了使用變得簡單,生命周期類允許其他對象查詢當(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.getCurrentState().isAtLeast(STARTED)) {
// connect if not connected
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop() {
// disconnect if connected
}
}
//源碼中的解釋:
/**
* Compares if this State is greater or equal to the given {@code state}.
*
* @param state State to compare with
* @return true if this State is greater or equal to the given {@code state}
*/
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
通過這個實現(xiàn),我們的LocationListener類完全是能感知生命周期的。如果我們需要從另一個activity或fragment中使用我們的LocationListener,我們只需要初始化它。所有的設(shè)置和銷毀等操作都是由類本身管理的。
實現(xiàn)自定義的 LifecycleOwner
這里要說的是,activity/fragment在Support Library 26.1.0以及以后的版本已經(jīng)實現(xiàn)了LifecycleOwner接口。
如果您希望生成一個實現(xiàn) LifecycleOwner
的自定義類,那么可以使用LifecycleRegistry
類,但是您需要將事件轉(zhuǎn)發(fā)到該類中,如下面的示例代碼所示:
public class MyActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry mLifecycleRegistry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLifecycleRegistry = new LifecycleRegistry(this);
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
}
@Override
public void onStart() {
super.onStart();
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
}
當(dāng)你去查看activity源碼時你會發(fā)現(xiàn),源碼也是基于這樣實現(xiàn)的。并沒有什么變化。
生命周期感知組件的最佳實踐
- 保持UI控制器(activity/fragment)盡可能簡單。它們不應(yīng)該去直接獲取數(shù)據(jù);相反,使用ViewModel
來獲取數(shù)據(jù),并觀察LiveData
對象以將數(shù)據(jù)的變化及時反應(yīng)到UI。 - 嘗試編寫數(shù)據(jù)驅(qū)動的UI,其中UI控制器的職責(zé)是在數(shù)據(jù)更改時更新UI,或者將用戶操作通知到ViewModel。
- 將數(shù)據(jù)的邏輯放在View模型類中。View模型應(yīng)充當(dāng)UI控制器和應(yīng)用程序其余部分之間的連接器。但是要小心,ViewModel的責(zé)任不是來獲取數(shù)據(jù)(例如,從一個網(wǎng)絡(luò))。相反,ViewModel應(yīng)該調(diào)用適當(dāng)?shù)慕M件來獲取數(shù)據(jù),然后將結(jié)果返回到UI控制器。
也就是說ViewModel只關(guān)心獲取數(shù)據(jù),但是不關(guān)心怎么獲取的。聽起來有一點繞口。打個比方,這里有很多管子,連接到一個大缸,我在一旁一直看著大缸里的水,監(jiān)測水位的變化。這里的我就相當(dāng)于UI及時的得到數(shù)據(jù)的變化,那么這個大缸就是ViewModel,它只關(guān)心缸里的水本身,至于水是從哪個管子里來的,不關(guān)心。那么管子就相當(dāng)于另一個概念Repository,它只專注于水從哪里來,也就是數(shù)據(jù)的獲取渠道。
