支持生命週期的組件執行操做以響應另外一個組件(例如Activity和fragment)的生命週期狀態更改。這些組件可幫助您生成組織性更好,而且一般更輕量的代碼,這些代碼更易於維護。常見的模式是在Activity和fragment的生命週期方法中實現依賴組件的操做。
可是,這種模式致使代碼的組織不良以及錯誤氾濫。經過使用生命週期感知組件,您能夠將相關組件的代碼從生命週期方法中移出並移入組件自己。htmlandroid.arch.lifecycle包提供了類和接口,可以讓您構建支持生命週期的組件,這些組件可根據活動或片斷的當前生命週期狀態自動調整其行爲
注意:要將android.arch.lifecycle導入到Android項目中,請參閱向項目添加組件。 javaAndroid框架中定義的大多數應用程序組件都附帶有生命週期。生命週期由操做系統或您的流程中運行的框架代碼管理。它們是Android如何工做和應用程序必須尊重它們的核心。不這樣作可能會觸發內存泄漏甚至應用程序崩潰。android
// 若是使用的是java 8要顯示聲明以下的 def lifecycle_version = "1.1.1" implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
想象一下,咱們有一個在屏幕上顯示設備位置的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; @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 } }
儘管這個示例看起來很好,但在實際的應用程序中,您最終會有太多的調用來管理UI和其餘組件,以響應當前的生命週期狀態。
管理多個組件會在生命週期方法中放置大量代碼,例如onStart()和onStop(),這使得它們很難維護。網絡
此外,沒法保證組件在活動或片斷中止以前啓動。
若是咱們須要執行一個長時間運行的操做,好比onStart()中的一些配置檢查,狀況尤爲如此。
這可能會致使onStop()方法在onStart()以前完成的爭用條件,從而使組件的存活時間超過所需的時間。app
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 -> { // what if this callback is invoked AFTER activity is stopped? if (result) { myLocationListener.start(); } }); } @Override public void onStop() { super.onStop(); myLocationListener.stop(); } }
android.arch.lifecycle包提供的類和接口可幫助您以彈性和獨立的方式解決這些問題。框架
Lifecycle是一個持有組件生命週期狀態(如Activity或Fragment)的信息的類,並容許其餘對象觀察此狀態。
Lifecycle使用兩個主要枚舉來跟蹤其關聯組件的生命週期狀態:編程語言
從框架和Lifecycle類派發的生命週期事件。
這些事件映射到Activities和fragments中的回調事件。ide
由Lifecycle對象跟蹤的組件的當前狀態。
測試
將狀態視爲圖中的節點,將事件視爲這些節點之間的邊界。
一個類能夠經過向其方法添加註解來監視組件的生命週期狀態。
而後,您能夠經過調用Lifecycle類的addObserver()方法並傳遞觀察者的實例來添加觀察者,以下例所示:
public class MyObserver implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void connectListener() { ... } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void disconnectListener() { ... } } myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
在上面的例子中,myLifecycleOwner對象實現了LifecycleOwner接口,這將在下一節中介紹。
LifecycleOwner是一個單一的方法接口,表示該類有一個Lifecycle。
它有一個方法getLifecycle(),它必須由class實現。
若是您試圖管理整個應用程序進程的生命週期,請參閱ProcessLifecycleOwner。
該接口從各個類(如Fragment和AppCompatActivity)抽象生命週期的全部權,並容許編寫與它們一塊兒工做的組件。
任何自定義應用程序類均可以實現LifecycleOwner接口
實現LifecycleObserver的組件能夠與實現LifecycleOwner的組件無縫協做,由於全部者能夠提供生命週期,觀察者能夠註冊觀察。
對於位置跟蹤示例,咱們可使MyLocationListener類實現LifecycleObserver,而後使用onCreate()方法中的活動生命週期對其進行初始化。
這容許MyLocationListener類是自給自足的,這意味着對生命週期狀態變化做出反應的邏輯在MyLocationListener中聲明,而不是在活動中聲明。
讓各個組件存儲本身的邏輯使得活動和片斷邏輯更容易管理。
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(); } }); } }
一個常見的用例就是避免在生命週期狀處於很差的狀態時調用某些回調。
例如,若是回調在保存活動狀態後(我本身理解爲onSaveInstanceState()方法執行後,也就是fragment不存在)運行fragment事務,則會觸發崩潰,所以咱們毫不但願調用該回調。
爲了簡化這個用例,生命週期類容許其餘對象查詢當前狀態。
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 } }
經過這個實現,咱們的LocationListener類徹底是生命週期感知的。
若是咱們須要使用來自其餘Activity或Fragment的LocationListener,咱們只須要初始化它。
全部的啓動和銷燬操做都由該類自己進行管理。
若是Library提供須要與Android生命週期配合使用的類,咱們建議您使用支持生命週期的組件。
您的Library客戶端能夠在客戶端無需手動生命週期管理便可輕鬆集成這些組件。
Support Library 26.1.0中的Fragment和Activity以及更高版本已經實現LifecycleOwner接口。
若是您想要建立LifecycleOwner的自定義類,則可使用LifecycleRegistry類,但須要將事件轉發到該類中,如如下代碼示例所示:
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; } }
支持生命週期的組件可讓您在各類狀況下更容易地管理生命週期。
一些例子是:
當Lifecycle屬於AppCompatActivity或Fragment時,Lifecycle的狀態將更改成CREATED,並在調用AppCompatActivity或Fragment的onSaveInstanceState()時調度ON_STOP事件。
當Fragment或AppCompatActivity的狀態經過onSaveInstanceState()保存時,UI被認爲是不可變的,直到ON_START被調用。嘗試在保存狀態後修改UI界面可能會致使應用程序的導航狀態不一致,這就是爲何若是應用程序在狀態保存後運行FragmentTransaction時FragmentManager會拋出異常。
有關詳細信息,詳情請參閱 commit()。
若是觀察者的關聯Lifecycle在STARTED以前,則LiveData經過避免調用其觀察者來防止這種邊緣狀況出現。
在幕後,它決定調用觀察者以前調用isAtLeast()。
不幸的是,AppCompatActivity的onStop()方法會在onSaveInstanceState()以後調用,這會在不容許UI狀態更改但生命週期還沒有移至CREATED狀態的狀況下留下空隙。
爲了防止出現這個問題,beta2版本中的Lifecycle類將lower狀態標記爲CREATED而不分派事件,即便事件直到onStop()被調用也未被分派,任何檢查當前狀態的代碼也都會得到真實值。
不幸的是,這個解決方案有兩個主要問題:
注意:爲了使此流程更簡單,並提供與舊版本的更好兼容性,從版本1.0.0-rc1開始,在調用onSaveInstanceState()而無需等待對onStop()的調用時,將Lifecycle對象標記爲CREATED,並調度onStop()方法。這不太可能影響您的代碼,但您須要注意這一點,由於它與API級別26及更低級別的Activity類中的調用順序不匹配。