天天看點

Jetpack — AAC架構元件之Lifecycle

一,前期基礎知識儲備

Jetpack — AAC架構元件之Lifecycle

1)AAC架構

Android Architecture Components,簡稱 AAC,一個處理UI的生命周期與資料的持久化的架構。

核心元件:Lifecycle, LiveData, ViewModel 以及 Room。

主要作用:

  • 通過它可以非常優雅的讓資料與界面互動
  • 并做一些持久化的東西
  • 高度解耦
  • 自動管理生命周期
  • 而且不用擔心記憶體洩漏的問題

2)不使用Lifecycle時的正常操作

解耦是軟體開發中永遠追求的,在Android開發中,解藕很大程度上表現為系統元件的生命周期與普通元件之間的解藕,因為普通元件在使用過程中需要依賴系統元件的的生命周期。

舉個例子,我們經常需要在頁面的onCreate()方法中對元件進行初始化,然後在onStop()中停止元件,或者在onDestory()方法中對進行進行銷毀。事實上,這樣的工作非常繁瑣,會讓頁面和頁面耦合度變高,但又不得不做,因為如果不即時的釋放資源,有可能會導緻記憶體洩露。例如,下面是一個在Activity的不同生命周期方法中監聽調用的例子,代碼如下:

public class MainActivity extends AppCompatActivity {
    private MyListener myListener;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myListener = new MyListener(MainActivity.this);
    }
    @Override
    protected void onStart() {
        super.onStart();
        myListener.start();
    }
    @Override
    protected void onStop() {
        super.onStop();
        myListener.stop();
    }
}

public class MyListener {
    public MyListener(Context context) {...}
    void start() {...}
    void stop() {...}
}
           

雖然,代碼執行起來并沒有什麼問題,但在實際開發中可能會有多個元件在Activity的生命周期方法中回調,這樣Activity的生命周期的方法中可能就需要編寫大量的代碼,這就使得它們難以維護。同時MyListener的構造方法中會傳入上下文對象,這就使得其持有了Activity的執行個體對象,在某些情況,這會引起記憶體洩漏。

我們希望在對元件進行管理時,不依賴頁面的生命周期的回調方法,同時當頁面生命周期發生改變時,也能夠即時的收到通知。

3)使用Lifecycle

Lifecycle 就是具有生命周期感覺能力的元件。簡單的了解就是,當Activity/Fragment的生命周期産生變化時,Lifecycle元件會感應相應的生命周期變化。是以隻要對其進行監聽,就可以實作不依賴頁面而能及時收到通知。

監聽Activity,Fragment的生命周期,其使用步驟非常簡單:

  • 實作生命周期觀察者接口 — 觀察者實作LifecycleObserver,方法上使用OnLifecycleEvent注解關注對應生命周期,生命周期觸發時就會執行對應方法。
  • 注冊生命周期觀察者 — 生命周期擁有者 使用getLifecycle()擷取Lifecycle執行個體,然後代用addObserver()添加觀察者。

二,上代碼,具體實作

Jetpack — AAC架構元件之Lifecycle

1)引入依賴,Androidx 項目建立時會自動添加依賴:

implementation 'androidx.appcompat:appcompat:1.1.0'
           

因為appcompat依賴了androidx.fragment,而androidx.fragment下依賴了ViewModel和 LiveData,LiveData内部又依賴了Lifecycle。

非Androidx 項目手動添加依賴:

implementation "android.arch.lifecycle:extensions:1.1.1"
           

2)注冊生命周期觀察者

public class MainActivity extends AppCompatActivity implements IView {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ① // 普通實作
          getLifecycle().addObserver(new CustomObserver());
          getLifecycle().addObserver(new LifecycleObserverClass());
        ③ // MVP實作
          homePresenter = new HomePresenter(this);
          getLifecycle().addObserver(homePresenter);
    }
}
           

Activity(或Fragment)是生命周期的擁有者,通過getLifecycle方法擷取到生命周期Lifecycle對象,Lifecycle對象使用addObserver方法給自己添加觀察者,即new出Observer對象。當Lifecycle的生命周期發生變化時,Observer就可以感覺到。如果使用了MVP的方式實作,則這裡的P層化身為觀察者。

3) 實作生命周期觀察者接口

常見的一共有三種實作方式,開發者可以根據自己的需求選擇适合自己的實作方式:

① 自定義類,直接實作LifecycleObserver接口,同時自定義方法,為方法打上注解,等到對應生命周期方法執行的時候,就可以調用定義好的方法了;

public class CustomObserver implements LifecycleObserver {
    @OnLifecycleEvent(value = Lifecycle.Event.ON_CREATE)
    public void connect_create() { }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_START)
    public void connect_start() { }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_RESUME)
    public void connect_resume() { }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_PAUSE)
    public void connect_pause() { }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_STOP)
    public void connect_stop() { }

    @OnLifecycleEvent(value = Lifecycle.Event.ON_DESTROY)
    public void connect_destroy() { }
}
           

首先CustomObserver實作了接口LifecycleObserver,LifecycleObserver用于标記一個類是生命周期觀察者。然後在connect_resume()、connect_pause()上分别都加了@OnLifecycleEvent注解,且value分别是Lifecycle.Event.ON_RESUME、Lifecycle.Event.ON_PAUSE,這個效果就是:connect_resume()會在ON_RESUME時執行,connect_pause()會在ON_PAUSE時執行。

② 自定義接口,繼承自LifecycleObserver接口,内部自定義方法,并且打上注解;而後自定義一個類進行實作:

interface ILifecycleObserver extends LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreate(LifecycleOwner owner);

    ... ...

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy(LifecycleOwner owner);

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onLifecycleChanged(LifecycleOwner owner, Lifecycle.Event event);
}

public class LifecycleObserverClass implements ILifecycleObserver {

    @Override
    public void onCreate(LifecycleOwner owner) { }
    
    ... ...

    @Override
    public void onDestroy(LifecycleOwner owner) { }

    @Override
    public void onLifecycleChanged(LifecycleOwner owner, Lifecycle.Event event) {
        Log.d(TAG, "onLifecycleChanged: " + owner + ",,,," + event);
    }
}
           

③ 自定義接口,繼承自LifecycleObserver接口,内部自定義方法,此時不打上注解;而後自定義一個類進行實作,類裡面實作接口方法後,打上注解:

interface FullLifecycle extends LifecycleObserver {
    void onCreate(LifecycleOwner owner);

    ... ...

    void onDestroy(LifecycleOwner owner);
}

public abstract class BasePresenter implements FullLifecycle {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    @Override
    public void onCreate(LifecycleOwner owner) { }
    
    ... ...

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    @Override
    public void onDestroy(LifecycleOwner owner) { }
}
           

注意:② ③中的自定義的構造方法中都傳入了一個LifecycleOwner的參數,這個參數可以在結合LiveData一起時使用。

4)聯合MVP進行實作

建立一個View接口對象,執行UI邏輯;

interface IView {
    void showView();

    void hideView();
}
           

建立一個HomePresenter,繼承自上面的BasePresenter,作為P層接口;

public class HomePresenter extends BasePresenter {
    private IView iView;
    public HomePresenter(IView view) {
        iView = view;
    }

    @Override
    public void onCreate(LifecycleOwner owner) {
        super.onCreate(owner);
        if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.CREATED)) {
            iView.showView();
        }
    }

    @Override
    public void onPause(LifecycleOwner owner) {
        super.onPause(owner);
        iView.hideView();
    }

    @Override
    public void onDestroy(LifecycleOwner owner) {
        super.onDestroy(owner);
        iView.hideView();
    }
}
           

Activity的代碼如下:

public class MainActivity extends AppCompatActivity implements IView {
    private HomePresenter homePresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        homePresenter = new HomePresenter(this);
        getLifecycle().addObserver(homePresenter);
    }

    @Override
    public void showView() { }

    @Override
    public void hideView() { }
}
           

這裡是讓Presenter實作LifecycleObserver接口,同樣在方法上注解要觸發的生命周期,最後在Activity中作為觀察者添加到Lifecycle中。

這樣做好處是啥呢?當Activity生命周期發生變化時,HomePresenter就可以感覺并執行方法,不需要在MainActivity的多個生命周期方法中調用HomePresenter的方法了。

所有方法調用操作都由元件本身管理:Presenter類自動感覺生命周期,如果需要在其他的Activity/Fragment也使用這個Presenter,隻需添加其為觀察者即可。

讓各個元件存儲自己的邏輯,減輕Activity/Fragment中代碼,更易于管理;

@Override
    public void onCreate(LifecycleOwner owner) {
        super.onCreate(owner);
        if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.CREATED)) {
            iView.showView();
        }
    }
           

另外,注意到 onCreate()中的回調,對目前生命周期狀态進行了檢查:至少處于CREATED狀态才會繼續執行showView()方法,也就是保證了Activity停止後不會調用方法,減少了記憶體洩漏的可能;

三,期間幾個重要的對象

  • LifecycleOwner:生命周期的事件分發者,該接口的實作類表示能夠為外部提供Lifecycle執行個體。系統架構中,接口的實作類為ComponentActivity和Fragment,兩者提供的Lifecycle對象,是系統架構實作中Lifecycle的唯一子類LifecycleRegistry。可以在 Activity、Fragment生命周期改變時,通過LifecycleRegistry類處理對應的生命周期事件,并通知 LifecycleObserver這個觀察者;
  • Lifecycle:是被觀察者,用于存儲有關元件(如 Activity 或 Fragment)的生命周期狀态的資訊,并允許其他對象觀察此狀态;
  • LifecycleObserver:生命周期的觀察者,該接口的實作類表示為關注生命周期的觀察者,可以通過被LifecycleRegistry類通過 addObserver(LifecycleObserver o)方法注冊,被注冊後,LifecycleObserver便可以觀察到LifecycleOwner對應的生命周期事件;
  • LifecycleRegistry:Lifecycle的實作類。控制中心。它負責控制state的轉換、接受分發event事件。
  • Lifecycle.Event:分派的生命周期事件。這些事件映射到 Activity 和 Fragment 中的回調事件。
  • Lifecycle.State:生命周期目前的狀态。Lifecycle元件的目前狀态。

Event枚舉:注意沒有onRestart對應的狀态;定一系列枚舉常量,和 Activity、Fragment 的生命周期是一一對應的,可以響應其生命周期,其中多了一個ON_ANY,它是可以比對任何事件的,Event 的使用是和 LifecycleObserver 配合使用的。

public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }
           

State枚舉:目前Lifecycle的自己的目前的狀态,它是和Event配合使用的。

public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
           

Event和State之間的關系:

Jetpack — AAC架構元件之Lifecycle

Lifecycle的常見的使用場景:

  • Lifecycle 的應用場景非常廣泛,我們可以利用 Lifecycle 的機制來幫助我們将一切跟生命周期有關的業務邏輯全都剝離出去,進行完全解耦。
    • 比如視訊的暫停與播放,
    • Handler 的消息移除,
    • 網絡請求的取消操作,
    • Presenter 的 attach&detach View
    • 暫停和恢複動畫繪制
    • 并且可以以一個更加優雅的方式實作,還我們一個更加幹淨可讀的 Activity & Fragment。
  • 關于網絡請求的取消操作
    • Retrofit 結合 Lifecycle, 将 Http 生命周期管理到極緻
  • 停止和開啟視訊緩沖
    • 使用支援生命周期的元件盡快開始視訊緩沖,但是将播放推遲到應用程式完全啟動。 還可以使用可識别生命周期的元件在應用程式銷毀時終止緩沖。
  • 啟動和停止網絡連接配接
    • 使用可感覺生命周期的元件可以在應用程式處于前台狀态時實時更新(流式傳輸)網絡資料,并在應用程式進入背景時自動暫停。
  • 暫停和恢複動畫繪制
    • 當應用程式在背景運作時,使用生命周期感覺元件處理暫停動畫繪制,并在應用程式在前台運作後恢複繪制。

最後總結:

  1. 先聲明了一個觀察者,用來監聽被觀察者(Activity/Fragment);
  2. 觀察者通過實作LifecycleObserver接口,使用注解來監聽被觀察者發生的變化;
  3. 那麼是如何監聽的,這次就使用到了lifecycle。lifecycle相當于一個橋梁,把兩者關聯在一起;
  4. 被觀察者通過實作LifecycleOwner接口先連接配接了橋梁;
  5. 觀察者則通過getLifecycle().addObserver()方法也建立起連接配接。

參考文章《Android Jetpack架構元件 — Lifecycle入坑指南》《Lifecycle詳細分析》《Jetpack AAC完整解析,Lifecycle 完全掌握》

繼續閱讀