Jetpack:Lifeccyle入門指南

爲何須要咱們管理Activity和Fragment的生命週期?這些不是Framework自動幫咱們搞定的麼?(手動黑人問號)剛看到這樣的標題我也是很懵逼,不就是onCreate->onSart()->onResume()->onPause()->onStop()->onDestory()麼?難道還有什麼高深的地方麼?android

題外話git

在講Data Bing Library的文章中,大多數同窗反饋在實際開發中沒什麼必要。由於沒深愛過,無法名正言順爲其正名。剛好週末逛到郭霖公衆號一篇講Data Bing 在RecyclerView的實踐,講的挺好,你們有空移步前去閱讀。引用《賣油翁的故事》道理->熟能生巧,愛得夠深,就能擦出火花。github

若是你對Data Binding Library有獨特的看法或見解,能夠前往Data Binding Library(數據綁定庫)討論數據庫

Abount Lifecycle-Aware Components

該組件能在像Activity、Fragment等等具備生命週期的組件發生狀態改變時,以輕量級的和易維護的代碼做出響應動做。bash

吃個栗子就懂意思了:網絡

//爲了考慮大多數同窗學習過Java,就貼Java的代碼
//定義個監聽類,用來在Activity生命週期發生變化時,對定位服務資源做相關處理
class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}
//在Activity中回調監聽類相關方法
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
    }
}
複製代碼

畢竟拿人手短,吃人嘴軟,吃了人家的栗子就得給人家分析。ide

這個栗子仍是挺簡單的,只是簡單調用了MyLocationListener對象的兩個回調方法,可是在實際開發中,大多數狀況下會在Activity的onCreate()、onStart()等等生命週期中作大量的業務邏輯處理和UI更新,並且若是不止一個監聽類須要被回調的話,就意味着要在Activity中管理多個其餘組件的生命週期或者回調。那代碼的維護性和可讀性就很是差。(另外,在發生某種競態條件的狀況下,可能會致使Activity的onStop()方法在onStart()方法前就發生了)post

爲了解決這種痛點,在包android.arch.lifecycle 中提供類和接口來獨立的管理Activity和Fragment組件的生命週期。學習

Lifecycle

生命週期是一個類包含組件的生命週期狀態的信息(例如Activity和Fragment),並容許其餘對象觀察到這個狀態。 Lifecycle對象以兩種主要的枚舉類型跟蹤它關聯組件的生命週期狀態:ui

  • Event Framework和Lifecycle類分發生命週期事件(Lifecycle Event),並映射到Activity或者Fragment的回調事件。
  • State Lifecycle對象跟蹤組件的當前狀態。

生命週期狀態
方框中的 INITALZIEDDESTROYED等等表示組件的狀態,而箭頭上的 ON_CREATEON_START等等則表示事件。假如Framework或者Lifecycle類分發 ON_CREATE事件,表示關聯的組件的狀態從初始化到onCreate狀態,對應調用組件的onCreate()方法。

經過在類的方法上添加註解來監聽組件的生命週期。而後將該類以觀察者形式添加到具備生命週期的類中。

//MyObserver做爲一個觀察者來監聽有生命週期的類
public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}
//myLifecycleOwner是一個實現了LifecycleOwner 接口的類,繼續看下文
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
複製代碼

LifecycleOwner

LifecycleOwner,是隻有一個getLifecycle()方法的接口,實現該接口的類表示具備生命週期。若是想管理整個應用的生命週期,用 ProcessLifecycleOwner代替LifecycleOwner。LifecycleOwner接口將全部具備生命週期的類的生命週期全部權抽象出來,以方即可以在其生命週期進行讀寫。實現了LifecycleObserver接口的類能夠註冊到實現了LifecycleOwner的類,以觀察對應組件的生命週期。例如上文的:

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
複製代碼

這樣作帶來的好處是什麼? 經過這種觀察者模式,能夠將日常根據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();
            }
        });
  }
}
複製代碼

講到這裏基本就已經知道如何使用Lifecycle-Aware Components管理Activity或Fragment的生命週期了。若是LifecycleObserver須要監聽其餘Activity或Fragment的生命週期,只須要從新初始化並註冊到新的Activity或Fragment便可。資源的設置和清除回收不須要咱們擔憂。

Custom LifecycleOwner

在Support Library 26.1.0和更高版本,Activity和Fragment已經默認實現了LifecycleOwner。若是要實現定製的LifecycleOwner,須要新建LifecycleRegistry對象,並將相關事件傳遞給它。

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}
複製代碼

最好實踐

  • 保持UI(Activity或Fragment)精簡。不要在Activity或Fragment中取獲取應用數據,採用ViewModel或者Livedata。也就是爲何有MVP、MVVM模式。
  • 嘗試寫數據驅動類型UI。在數據發生變化的時候經過UI控制器更新UI或者通知用戶進行操做。
  • 把數據的處理邏輯放到ViewModel類中。ViewModel做爲UI界面與數據的橋樑,處理數據與UI界面交互的邏輯。注意不是獲取數據的邏輯,例如獲取網絡數據或者數據庫數據。
  • 使用數據綁定庫(Data Binding Library)在UI界面和UI控制器之間進行維護。這樣有利於減小在Activity或Fragment中更新UI的代碼。在Java中可使用Butter Knife庫。
  • 若是UI界面很複雜,能夠創建一個主持(Presenter)類去處理視圖。MVP模式?
  • 使用Kotlin協同機制管理耗時任務。

使用lifecycle-aware components的場景

lifecycle-aware組件在不一樣狀況能讓咱們更方便的管理Acitivity和Fragment的生命週期。那在什麼情景下適合使用該組件呢?

  • 粗細粒度的切換。例如在定位中,若是當前界面可見,那麼定位精度應該更細,定位請求更頻繁,以提升響應性。當切換到後臺時,請求定位的頻率就要放緩,以下降功耗
  • 開始和中止視頻緩衝。這個是高手,在應用加載的時候儘早緩衝視頻,減小用戶等待時間在應用退出是結束緩衝。
  • 開始和中止網絡鏈接。根據App狀態自動切換鏈接的狀態。
  • 開始和中止繪製圖片。應用在後臺時不會繪製,返回前臺繼續繪製。

存在的一些問題

當Fragment或AppCompatActivity在調用onSaveInstanceState()方法保存狀態後,它們的視圖在ON_START事件被調用以前是不會改變的,在這期間UI被更改會引發不一致的問題,這就是爲何FragmentManager在狀態保存後運行FragmentTransaction會拋出異常。

所以若是AppCompatActivity的onStop()方法在調用onSaveInstanceState()方法以後,就會形成一個缺口:UI狀態改變是不容許,但生命週期尚未改成CREATED的狀態。爲此,Lifecycle類經過將狀態標記爲CREATED,但直到調用onStop()方法前,不分發該事件,此時去檢測當前的狀態也可得到真實的值。可是還存在如下兩個問題:

  • 在Android 6.0和更低版本,系統調用onSaveInstanceState()方法,但它不必定調用onStop()方法。這樣就會形成事件沒法分發,潛在的致使觀察者覺得lifecycle處於活動狀態,儘管此時它處於中止狀態。
  • 任何想要在LiveData暴露相似行爲的類必須實現Lifecycle 版本 beta 2 和更低版本提供的方法。

更多信息請參考官網

總結

本文是對官網知識的理解或翻譯,建議再進一步閱讀原文,畢竟原文才是原汁原味,知識點也多。 從第一次看官網懵懵懂懂,到開始瞭解,又掌握一個知識點。不只光講Lifecycle-Aware Components的知識點,還講到日常開發應用的最佳實踐,這些對實際開發都有很強指導做用。

Welcom to visit my github

本文是Jetpack系列文章第二篇

第一篇: Jetpack:你還在findViewById麼?

第三篇: Jetpack:在數據變化時如何優雅更新Views數據

相關文章
相關標籤/搜索