將依賴於生命週期的程式碼直接寫在Activity 或 Fragment 會導致程式碼條理性很差並且會擴散錯誤。
透過Lifecycle可以將依賴元件的程式碼從生命週期方法移入元件本身中。也就是說,元件內部可以感知到Activity 或者 Fragment的生命週期
這篇文章具體展開說一下Lifecycle 的用法
預備知識Lifecycle 中的事件和狀態Lifecycle 透過兩個列舉型別:Event 和 State 來 對應 Android 檢視元件的生命週期:
// 事件 public enum Event { ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY } //狀態 /** * Lifecycle states. You can consider the states as the nodes in a graph and * {@link Event}s as the edges between these nodes. */ public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } }
官方註釋告訴我們
你可以將 States 想成一張圖中的點,將 Event 想成是圖中連線這些點的邊。
也就是這一張圖:
至於這張圖的箭頭和狀態是怎麼來的,可以在原始碼中(LifecycleRegister)找到答案:
static State getStateAfter(Event event) { switch (event) { case ON_CREATE: case ON_STOP: return CREATED; case ON_START: case ON_PAUSE: return STARTED; case ON_RESUME: return RESUMED; case ON_DESTROY: return DESTROYED; case ON_ANY: break; } throw new IllegalArgumentException("Unexpected event value " + event); }
邏輯很清楚的可以對應到圖中的狀態與事件的轉換,另外還有兩個方法:downEvent(State state) upEvent(State state)也說明了上圖中的關係,讀者有興趣的話可以自己檢視原始碼
每一個 Event 對映到Activity或者Fragmnet的其中一個生命週期的回撥每一個 State 反應了由 Lifecycle 跟蹤元件的當前狀態⚠️ 不要把Lifecycle想得很神奇,其實質就是簡單的觀察者模式,首先在檢視控制器中註冊觀察者,Android原始碼會在生命週期變化後去分發對應生命週期的事件,由LifecycleRegister去呼叫自己實現的LifecycleEventObserver(上面透過註解方法實現的LifecycleObserve最終也會被解析成LifecycleEventObserver)中的onStateChanged方法。具體原理會在Lifecycle第三篇說到
LifecycleOwnerpublic interface LifecycleOwner { @NonNull Lifecycle getLifecycle();}
單一方法的介面,顧名思義:可以將實現了這個介面的類理解為 具有Lifecycle的元件。可以很容易的想到 Activity 和 Fragment 已經實現了這個介面:
public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner, ViewModelStoreOwner, ...
public class Fragment implements LifecycleOwner, ViewModelStoreOwner ...
所以在使用Lifecycle時可以在Activity或Fragment中直接呼叫介面方法getLifecycle()
lifecycle.addObserver(NetStateManager)
新增觀察者
除此之外,我們也可以透過實現LifecycleOwner來自定義,在Lifecycle系列文章的最後會實現一個自定義LifeOwner幫助大家更好理解
LifecycleObserver使用Lifecycle的第一步就是要實現LifecycleObserver:
object ContentPlayer : LifecycleObserver{ @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun prepare(context: Context) { //播放器的準備工作 } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun unAttach() { //釋放當前持有的Activity資源 } // 開始播放 fun Play(content: String) { ... } ...}
透過方法註釋,明確指定該方法被呼叫的時機。在上面的例子中,如果在Acitivity中新增ContentPlayer觀察者,那麼perpare()方法會在Activity建立時呼叫,unAttach()會在Activity銷燬時呼叫。
實現LifecycleObserver不是隻有這一種方法。已經提供了幾種內建實現供我們選擇:比如官方已經內建實現了LifecycleObserver的 LifecycleEventObservser
object ContentPlayer : LifecycleEventObserver { override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { when (event) { Lifecycle.Event.ON_CREATE -> TODO() Lifecycle.Event.ON_START -> TODO() Lifecycle.Event.ON_RESUME -> TODO() Lifecycle.Event.ON_PAUSE -> TODO() Lifecycle.Event.ON_STOP -> TODO() Lifecycle.Event.ON_DESTROY -> TODO() Lifecycle.Event.ON_ANY -> TODO() } }}
每當檢視控制器的狀態發生改變,都會將事件回撥給onStateChanged(),在不同的事件分支中實現自己想要實現的邏輯。
實際上在使用第一種使用註解的方法的情況下,在執行時LifecycleRegister這個類會透過反射或者apt來將LifecycleObserver轉化成LifecycleEventObservser,所以有些情況下為了避免反射帶來的消耗,可以優先考慮實現LifecycleEventObservser
新增觀察者最後只需要在Activity的onCreated方法完成最後一步:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... lifecycle.addObserver(ContentPlayer) }
最後需要考慮一種情況:如果在Observser中觀察了ON_CREATE事件,而我們在Activity的onResume才註冊觀察者,還能收到發生在onResume()之前的ON_CREATE事件嗎?
object Observer : LifecycleObserver{ @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun onCreate(context: Context) { Log.d(TAG, "觀察onCreate 事件") } @OnLifecycleEvent(Lifecycle.Event.ON_Start) fun onStart(context: Context) { Log.d(TAG, "觀察onStart 事件") } ...}
然後在Activity的onResume時才註冊觀察者
override fun onResume(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... lifecycle.addObserver(Observser) }
答案是:可以。所以大家放心使用