Android 架構組件之 LifeCycle詳解

一、Lifecycle介紹

lifecycle官方文檔地址:
https://developer.android.com/topic/libraries/architecture/lifecyclehtml

爲何要使用lifecycle?
activity 和fragment 是有聲明週期的,有時候,咱們的不少操做須要寫在聲明週期的方法中,好比,下載,文件操做等,這樣不少狀況下回致使,咱們在activity中的聲明週期方法中寫愈來愈多的代碼,activity或者fragment 愈來愈臃腫,代碼維護愈來愈困難。 使用lifecycle就能夠很好的解決這類問題。
lifecycle代碼簡潔,咱們能夠經過實現LifecycleObserver 接口,來監聽聲明週期,而後咱們在activity和fragment中去註冊監聽。

二、幾個重要的類和接口

  • Lifecycle
    Lifecycle是一個持有組件生命週期狀態(如Activity或Fragment)的信息的類,並容許其餘對象觀察此狀態。
  • Event :從框架和Lifecycle類派發的生命週期事件。這些事件映射到活動和片斷中的回調事件。
  • State :由Lifecycle對象跟蹤的組件的當前狀態。
  • LifecycleOwner (重要)Lifecycle持有者
  • 實現該接口的類持有生命週期(Lifecycle對象),該接口的生命週期(Lifecycle對象)的改變會被其註冊的觀察者LifecycleObserver觀察到並觸發其對應的事件。
  • LifecycleObserver(重要)Lifecycle觀察者
  • 實現該接口的類,經過註解的方式,能夠經過被LifecycleOwner類的addObserver(LifecycleObserver o)方法註冊,被註冊後,LifecycleObserver即可以觀察到LifecycleOwner的生命週期事件。

三、LifeCycle中兩個重要的接口LifeCycleOwner和LifecycleObserver 的使用

(1)LifecycleOwner(生命週期持有者接口)
官網介紹: LifecycleOwner是一個單一的方法接口,表示該類有一個 Lifecycle。它有一個方法, getLifecycle()這個方法 必須由這個類來實現。若是您試圖管理整個應用程序進程的生命週期,請參閱 ProcessLifecycleOwner。該接口從各個類(如Fragment和AppCompatActivity)抽象生命週期的全部權,並容許編寫與它們一塊兒工做的組件。
任何自定義應用程序類均可以實現LifecycleOwner接口
實現LifecycleObserver的組件與實現LifecycleOwner的組件無縫協做,由於全部者能夠提供生命週期,觀察者能夠註冊以觀看

簡單來講,LifecycleOwner就是一個接口,誰繼承了它,就持有了lifecycle對象。而後就能夠調用getLifecycle()方法獲取繼承了抽象類Lifecycle的LifecycleRegistry,而後調用 addObserver(@NonNull LifecycleObserver observer) 方法來註冊監聽。
這樣,該接口的生命週期(Lifecycle對象)的改變會被其註冊的觀察者LifecycleObserver觀察到並觸發其對應的事件。java

注意:Support Library 26.1.0 及其之後的版本,Activity 和Fragment 已經實現了LifecycleOwner 接口,因此,咱們能夠直接在Activity 和Fragment中使用getLifecycle()方法來獲取lifecycle對象,來添加觀察者監聽。android

(2)LifecycleObserver(生命週期觀察者接口)
LifecycleObserver 是一個觀察者接口,實現了它,能夠經過註解或者繼承的方式,來管理聲明週期的監聽。只要在持有lifecycle的類中註冊了它,當聲明週期發生變化時,它就能收到,進行咱們自定義的操做。

兩種實現方式:編程

  1. 實現DefultLifecyceObserver接口,而後重寫裏面生命週期方法;
  2. 直接實現LifecycleObserver接口,而後經過註解的方式來接收生命週期的變化;

Lifecycle.java文檔中是建議使用第一種方式,由於文檔中說明了,隨着Java8成爲主流,註解的方式會被棄用。DefaultLifecycleObserver是須要另外聲明的java8 好比下面
GenericLifecycleObserver,FullLifecycleObserver,DefaultLifecycleObserver 這三個接口都是直接或者間接繼承的LifecycleObserverapi

// 若是使用的是java 8要顯示聲明以下的
def lifecycle_version = "1.1.1"
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

在這裏插入圖片描述

三、開始使用Lifecycle

咱們寫個測試代碼,首先,咱們要測試一下,到底LifecycleObserver到底能不能監聽到聲明週期的變化。而且實驗下上圖中的聲明週期狀態
先寫兩個簡單的Activity,FirstActivity 和SecondActivity, 單純的一個跳轉。網絡

public class FirstActivity extends AppCompatActivity {

    private Button firstBtn;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_activity_layout);
        initView();
        initListener();
    }

    private void initView() {
        firstBtn = findViewById(R.id.first_btn);
    }

    private void initListener() {
        firstBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}

接下來,咱們要作的是要寫一個須要擁有聲明週期的類,正常咱們自定義控件啊,或者作其餘邏輯的類,是沒有聲明週期的,如今有了LifecycleObserver,咱們可讓一個普通的類擁有感知聲明週期變化的能力。好比,如今自定義一個,MyObserver類。框架

public class MyObserver implements DefaultLifecycleObserver{
   private static final String TAG = "MyListener";

    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onCreate()");
        Log.d(TAG,"當前生命週期狀態="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onStart()");
        Log.d(TAG,"當前生命週期狀態="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onResume()");
        Log.d(TAG,"當前生命週期狀態="+lifecycle.getCurrentState().name());
     
    }

    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onPause()");
        Log.d(TAG,"當前生命週期狀態="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onStop()");
        Log.d(TAG,"當前生命週期狀態="+lifecycle.getCurrentState().name());
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        Log.d(TAG,"onDestroy() ");
        Log.d(TAG,"當前生命週期狀態="+lifecycle.getCurrentState().name());
    }


}

咱們採起的是,直接繼承DefaultLifecycleObserver接口,來實現它全部的方法。咱們在裏面作了log,來查看,是否這個類,收到了activity聲明週期的變化。
而後,要作的就是註冊監聽
在Activity 的OnCreate方法中,調用getLifecycle();編程語言

public class FirstActivity extends AppCompatActivity {

    private Button firstBtn;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_activity_layout);
        initView();
        initListener();
        //添加了這一行代碼
        getLifecycle().addObserver(new MyObserver());
    }

    private void initView() {
        firstBtn = findViewById(R.id.first_btn);
    }

    private void initListener() {
        firstBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}

能夠看到,api26,.1之後,Activity中能夠直接 getLifecycle().addObserver(new MyObserver()); 這樣,就已經註冊了聲明週期觀察者的監聽。運行查看log
啓動FirstActivity後,MyObserver類已經監聽到了Activity的聲明週期方法
而且,和圖中表示一致,各個聲明週期方法對應相應的節點。必定要清楚,後面會用到。好比,onResume()方法執行後,Activity處於RESUME狀態,咱們能夠經過判斷這個狀態來作一些事情ide

在這裏插入圖片描述
點擊跳轉到SecondActivity
在這裏插入圖片描述
能夠看到,FirstActivity聲明週期走了onPause onStop,MyObserver也成功監聽到了,繼續返回FirstActivity
在這裏插入圖片描述
最後,點擊返回鍵,退出FirstActivity,
在這裏插入圖片描述測試

經過這個簡單的小例子,咱們看到了 咱們的類,只要實現了 LifecycleObserver接口,而後,在Activity 或者Fragment中 經過getLifecycle().addObserver()方法,把這個類的對象傳入,就能夠實現聲明週期的感應監聽。

固然,咱們能夠再初始化這個類的時候,把Lifecycle對象傳入,那咱們自定義的類就能夠本身去管理聲明週期,而不依賴activity或者fragment。 這樣,activity在使用此類的時候就沒必要關係聲明週期的問題,由於,在這個類裏面咱們已經處理了。好比: 給MyObserver類 添加一個構造方法,傳入一個Lifecycle對象。

要注意的是:
生命週期狀態爲RESUMED時表示,當前activity 是在前臺,而且可交互也就是onResume()執行後

生命週期狀態爲STARTED時,表示當前activity處於可見可是不可交互,也就是onStart()方法剛執行完或者onPause()方法剛執行完的狀態

生命週期狀態爲CREATED,表示onCreate()方法剛剛執行完或者onStop()方法剛剛執行完,也就是當前activity不在前臺,可是也沒有處於銷燬狀態。

生命週期狀態爲DESTORYED,表示當前Activity還不存在,沒有被建立或者已經銷燬,咱們一般考慮比較多的就是,onDestory()方法執行後,當前Activity已經銷燬。

因此,若是咱們要保證在Activity或者Fragment的有效生命週期內進行的操做,必須判斷,當前lifecycle的狀態是否至少是CREATED狀態,避免Activity或者fragment銷燬了之後,回調或者網絡請求才回來,此時作一些操做會致使異常。

添加如下代碼,就是咱們把lifecycle對象傳給觀察者,讓它本身去判斷回調後的代碼,保證至少是CREATED狀態

private Lifecycle lifecycle;
   public MyObserver(Lifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }
//而後再相應的回調方法中使用下面代碼判斷,保證數據回調回來,當前activity是存在的
    if (lifecycle.getCurrentState().isAtLeast(CREATED)) {
            //這裏只是示例,不必定是CREATED
    }

這裏用到了Lifecycle類的方法,下面咱們看一下Lifecycle的源碼

public abstract class Lifecycle {
    @MainThread  //添加將在LifecycleOwner更改狀態時通知的LifecycleObserver。
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    @MainThread //從觀察者列表中刪除給定的觀察者。
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    @MainThread //返回生命週期的當前狀態。
    public abstract State getCurrentState();

    @SuppressWarnings("WeakerAccess")
    public enum Event {

        ON_CREATE,//用於onCreate事件的常量LifecycleOwner。

        ON_START,

        ON_RESUME,

        ON_PAUSE,

        ON_STOP,

        ON_DESTROY,

        ON_ANY //一個Event能夠用來匹配全部事件的常數。 
    }

    @SuppressWarnings("WeakerAccess")
    public enum State {

        DESTROYED,
        INITIALIZED, //LifecycleOwner的初始化狀態。 
        CREATED, 
        STARTED,
        RESUMED;
                //比較此狀態是否大於或等於給定值state。
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
}

/**
 * Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on
 * {@link OnLifecycleEvent} annotated methods.
 * <p>
 * @see Lifecycle Lifecycle - for samples and usage patterns.
 */
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {

}

就是一個抽象類,註釋已經很詳細了,應該不用解釋了

最後借用下官網的-生命週期感知組件的最佳實戰

  1. 儘量保持您的UI控制器(活動和片斷)儘量精簡。他們不該該試圖獲取他們本身的數據;相反,使用ViewModel來作到這一點,並觀察一個LiveData對象來反映更改回視圖。
  2. 嘗試編寫數據驅動的用戶界面,其中您的用戶界面控制器的職責是在數據更改時更新視圖,或將用戶操做通知給ViewModel。
  3. 把你的數據邏輯放在ViewModel類中。ViewModel應做爲您的UI控制器和其餘應用程序之間的鏈接器。但要當心,ViewModel不負責提取數據(例如,來自網絡)。相反,ViewModel應調用相應的組件來獲取數據,而後將結果提供給UI控制器。
  4. 使用dataBinding在視圖和UI控制器之間保持乾淨的界面。這使您可使您的視圖更具說明性,並最大限度地減小須要在活動和片斷中編寫的更新代碼。

若是你喜歡用Java編程語言來作到這一點,可使用像Butter Knife這樣的庫來避免樣板代碼而且有更好的抽象。

  1. 若是您的UI很複雜,請考慮建立一個演示者類(presenter)來處理UI修改。這多是一項艱鉅的任務,但它可使您的UI組件更易於測試。
  2. 避免在ViewModel中引用View或Activity上下文。

若是ViewModel超出活動(在配置更改的狀況下),則活動會泄漏而且垃圾收集器沒法正確處理。

借用下https://blog.csdn.net/zhuzp_b... 做者的兩張圖,更清晰,對於相信信息,可到做者博客去查看相關講解
這裏寫圖片描述

這裏寫圖片描述

相關文章
相關標籤/搜索