Jetpack系列 - Lifecycle從入門到原始碼

雷加發表於2019-02-28

這篇文章旨在用最簡單的方式教會你Lifecycle如何使用,及它的工作原理。

Lifecycle介紹

Lifecycle是Google推出的JetPack框架元件的一個,主要是用來感知Activity和Fragment的生命週期,可以幫你寫出更簡潔,通用的程式碼。

Lifecycle使用

總共兩步

  1. 第一步,編寫自己的Observer類檔案,並實現對應的監聽方法,通過註解實現對響應生命週期方法的監聽,程式碼如下:
public class MyLifeObserver implements LifecycleObserver {

  private static final String TAG = "MyLifeObserver";

  // OnLifecycleEvent()內的註解Lifecycle.Event.XXX 對應不同的生命週期方法,你可以根據需要監聽不同的生命週期方法。
  // 方法名可以隨意,這裡為了方便理解定義為onResumeListener()。
  @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
  public void onResumeListener() {
    Log.d(TAG, "onResume: ");
  }

  @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
  public void onPauseListener() {
    Log.d(TAG, "onPause: ");
  }

  @OnLifecycleEvent(Event.ON_DESTROY)
  public void onDestoryListener() {
    Log.d(TAG, "onDestory: ");
  }
複製程式碼
  1. 第二步在被監聽的Activity/Fragment內註冊:
public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getLifecycle().addObserver(new MyLifeObserver());
  }
}
複製程式碼

不管你信不信,程式碼已經寫完了!

Jetpack系列 - Lifecycle從入門到原始碼

我們跑一下程式碼:

2019-02-28 12:00:40.068 com.example.lifecycledemo D/MyLifeObserver: onResume: 
2019-02-28 12:00:46.091 com.example.lifecycledemo D/MyLifeObserver: onPause: 
2019-02-28 12:00:46.416 com.example.lifecycledemo D/MyLifeObserver: onDestory: 
複製程式碼

Log 顯示我們寫的 Observer 內的方法的確在 Activity 的指定週期內執行了。恭喜你,已經能夠使用 Lifecycle 了
但是注意幾點:

  1. 通常我們會 把MyLifeObserver 作為內部類寫在另一個 Activity/Fragment 中,以方便在監控到生命週期方法後做一些業務操作,以上程式碼為了快速看到效果而做了省略。
  2. 注意上面 Activity 的程式碼中,我們的 Activity 繼承了AppCompatActivity,AppCompatActivity 和 Fragment 都實現了LifecycleOwner 介面(Support Library 26.1.0之後的版本),所以可以直接拿來使用。如果你被監控的 Actiivty 是自定義的 Activity,需要手動繼 承LifecycleOwner,具體操作如下:
1. 實現LifecycleOwner介面,並重寫getLifecycle方法。
2. 手動在每個生命週期方法中做標記。
複製程式碼

具體程式碼如下:

public class MyActivity extends Activity implements LifecycleOwner {
  private LifecycleRegistry mLifecycleRegistry;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    //建立Lifecycle物件
    mLifecycleRegistry = *new*LifecycleRegistry(this);
    //做標記
    mLifecycleRegistry.markState(Lifecycle.State.CREATED);
    //新增觀察者
    getLifecycle().addObserver(new MyLifeObserver());
  }

  @NonNull
  @Override
  public Lifecycle getLifecycle() {
    return mLifecycleRegistry;
  }

  @Override
  public void onStart() {
    super.onStart();
    //做標記
    mLifecycleRegistry.markState(Lifecycle.State.STARTED);
  }

  @Override
  protected void onResume() {
    super.onResume();
    //做標記
    mLifecycleRegistry.markState(Lifecycle.State.RESUMED);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    //做標記
    mLifecycleRegistry.markState(Lifecycle.State.DESTROYED); 
  }
}
複製程式碼

至此,Lifecycle 的使用方法已經介紹完了,因為 AppCompatActivity 已經幫我們實現了 LifecycleOwner 介面,所以同學們注意活學活用
比如:在封裝網路請求工具時候,傳入當前 Activity 物件,當 Activity 物件生命週期為 Destory 時,撤銷請求網路的操作。 Lifecycle 用武之地還有很多,這裡只介紹最基礎的,你現在可以思考如何通過 Lifecycle 來優化你的專案了。
如果你對Lifecyle的工作原理有興趣,請繼續閱讀,我會帶著你從原始碼一步一步完全理解 Lifecycle 的工作原理。 如果沒有興趣,可以直接拉到文章末尾看總結~

Lifecycle的工作原理

我們就以使用到的幾個類為切入口,分析 Lifecycle 的工作原理。 我們主要點進這幾個類看(Crtl+單擊類名):LifecycleOwner.java,Lifecycle.java,LifecycleRegistry.java

LifecycleOwner.java

這個很簡單,LifecycleOwner定義了一個getLifecycle()方法,通過@NonNull強制我們返回Lifecycle物件。程式碼如下:

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}

複製程式碼

Lifecycle.java

程式碼如下:

public abstract class Lifecycle {
 
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    @MainThread
    @NonNull
    public abstract State getCurrentState();

    @SuppressWarnings("WeakerAccess")
    public enum Event {
    ON_CREATE,ON_START,ON_RESUME,ON_PAUSE,ON_STOP,
    ON_DESTROY,ON_ANY
    }

    @SuppressWarnings("WeakerAccess")
    public enum State {

        DESTROYED,INITIALIZED,CREATED,STARTED, RESUMED;

        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
}
複製程式碼

Lifecycle的程式碼也並不多,注意它是一個抽象類。Lifecycle內部通過兩個列舉分別定義了元件的生命週期的狀態事件。 下面這張圖摘自Android開發者官網,介紹了StateEvent的關係:

摘自Android開發者官網

簡單說下這個圖怎麼看:看箭頭,比如 ON_CREATE 箭頭表示:State 從 INITIALIZED 變為 CREATED,會觸發 ON_CREATE 的 Event。依次類推。

LifecycleRegistry.java

這個類的程式碼比較多,是 Lifecycle 的子類,也是監聽元件宣告週期的核心類。我們就從使用到的方法一個一個來看:

A.構造方法,主要初始化了 mLifecycleOwner 和當前元件的狀態(mState),沒什麼說的。

publicLifecycleRegistry(@NonNull LifecycleOwner provider) {
  mLifecycleOwner = new WeakReference<>(provider);
  mState = INITIALIZED;
}
複製程式碼

B. 我們在 Lifecycle 的使用部分,繼承了 LifecycleOwner,並在元件的生命週期內呼叫了 markState()方法。點進去如下:

public void markState(@NonNull State state) {
  moveToState(state);
}
複製程式碼

C. 省去了一些複雜邏輯的程式碼,我們找到了這個核心的方法 sync():

private void moveToState(State next) {
 ...
  mHandlingEvent = true;
  sync();
  mHandlingEvent = false;
}

複製程式碼

D. 同樣在 sync()方法中,忽略掉邏輯程式碼,我們發現了正真執行的兩個方法:backwardPass(),forwardPass()

private void sync() {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    while(!isSynced()) {
        mNewEventOccurred = false;
        if(mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState > newest = mObserverMap.newest();
        if(!mNewEventOccurred && newest != null && mState.compareTo(newest.getValue().mState) > 0) {
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

複製程式碼

E. 在 backwardPass()和 forwardPass(),呼叫了 observer.dispatchEvent(),看名字想必就是傳送事件的方法了:

private void forwardPass(LifecycleOwner lifecycleOwner) {
    ...
            observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
    ...
}

private void backwardPass(LifecycleOwner lifecycleOwner) {
 ...
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
 ...
}
複製程式碼

F. 我們點選 dispatchEvent()方法,進入了下面這個靜態內部類中,這個類中,就可以確定了:Observer(下面程式碼中的 mLifecycleObserver)觸監聽定生命週期的方法在這裡被觸發了。 但是我們如何確定這個方法的 mLifecycleObserver 就是我們實現的 Observer 呢?這個靜態類還有一個方法,我們點選一下看它在哪裡被呼叫了:

static class ObserverWithState {
    State mState;
    GenericLifecycleObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.getCallback(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}
複製程式碼

G. 很高興,我們來到了 addObserver()方法,你一定還記得我們在講解 Lifecycle 使用部分是,繫結 Observer 就是使用這個方法。

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    ObserverWithState*statefulObserver = new ObserverWithState(observer, initialState);
    ObserverWithState*previous = mObserverMap.putIfAbsent(observer, statefulObserver);
...
}
複製程式碼

H. 最後我們看一眼 LifecycleObserver介面(觀察者),發現它是空的。其實我們看到註解應該猜到,系統是通過 apt-processor(註釋處理器)將我們的 Observer 轉換成 Lifecycle 真正需要型別 的Observer,下面是 OnLifecycleEvent 註解的宣告:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnLifecycleEvent {
    Lifecycle.Event value();
}
複製程式碼

總結

看到這裡,相信大家對 Lifecycle 的工作原理已經理解的差不多了吧,跟介面回撥類似,我們建立了 Obersver 的物件,然後將 Obersver 的引用交給 Lifecycle,在元件生命週期方法執行時,呼叫 Observer 的相應的方法。

Jetpack系列 - Lifecycle從入門到原始碼
當然,我們自己也可以寫一套介面回撥來監控元件的生命週期,但是我們不得不考慮在哪裡設定監聽器,生命週期的問題。 其實我們使用 Lifecycle 真正的理由是,Lifecycle(LifecycleRegistry)類幫我們處理了大量的與宿主元件生命週期相關的問題,使我們的程式碼更簡潔。專心處理業務邏輯即可。

END

我是雷加,如果您喜歡我的文章,請留下你的贊;如有疑問和建議,請在評論區留言
我的Github,歡迎關注~

Jetpack 專欄:
Lifecycle:Jetpack系列 - Lifecycle從入門到原始碼
ViewModel:Jetpack系列 - ViewModel從入門到原始碼
LiveData:Jetpack系列 - LiveData從入門到原始碼
Palette:Jetpack系列 - Palette 入門指南

--------------------------------------- The End

相關文章