Lifecycle 解惑

一、Lifecycle & LifecyclRegistry

1. Lifecycler

Lifecycle 是一個抽象類,它的結構很簡單:

  • 一系列生命周期事件的枚舉定義:Event。ON_CREATE...ON_DESTROY, ON_ANY
  • 一系列當前所處狀態(tài)的定義:StateDESTROYED,INITIALIZEDCREATED,STARTED,RESUMED。
  • 添加、移除觀察者的 addObserverremoveObserver 方法
    上面的前兩點其實是有關聯性的,是由 事件的變化 驅動 狀態(tài)的變化。它們之間的關系如下圖所示:
    image.png

我們來看看系統(tǒng)源碼中是如何表現上面關系的:
INITIALIZED 是一個初態(tài),因此在 Lificycle 的唯一子類 LifecycleRegistry 的構造函數中就將 Lifecycle 的初始狀態(tài)設置為 INITIALIZED

public LifecycleRegistry(@NonNull LifecycleOwner provider) {
    mLifecycleOwner = new WeakReference<>(provider);
    mState = INITIALIZED;
}

方法 RegistryLifecycle.handleLifecycleEvent(Lifecycle.Event) 是統(tǒng)一接收 Event 并將 State 狀態(tài)流轉到相應值的地方。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    State next = getStateAfter(event);
    moveToState(next);
}

我們再看 getStateAfter 方法,其中寫死了上圖中狀態(tài)流轉的對應關系:

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);
}

而調用 handleLifecycleEvent 的地方也是 Fragment/Activity 生命周期回調的地方,這樣就把生命周期回調 → EventState 綁定了起來:

image.png

  • Event.ON_CREATE 的發(fā)射是在生命周期回調 onCreate 之后,但是 Event.ON_DESTROY 的發(fā)射是在生命周期回調 onDestroy 之前。事實上,所有的創(chuàng)建事件都在生命周期回調之后,所有的銷毀事件都在生命周期回調之前。
// androidx.fragment.app.Fragment
void performCreate(Bundle savedInstanceState) {
   mChildFragmentManager.noteStateNotSaved();
   // 標記當前的生命周期狀態(tài)
   mState = CREATED;
   mCalled = false;
   mSavedStateRegistryController.performRestore(savedInstanceState);
   // 生命周期回調
   onCreate(savedInstanceState);
   mIsCreated = true;
   if (!mCalled) {
       throw new SuperNotCalledException("Fragment " + this
               + " did not call through to super.onCreate()");
   }
   // 發(fā)射 lifecycle 事件,更新 lifecycle 狀態(tài)
   mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}

void performDestroy() {
   mChildFragmentManager.dispatchDestroy();
   // 發(fā)射 lifecycle 事件,更新 lifecycle 狀態(tài)
   mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
   mState = ATTACHED;
   mCalled = false;
   mIsCreated = false;
   // 生命周期回調
   onDestroy();
   if (!mCalled) {
       throw new SuperNotCalledException("Fragment " + this
               + " did not call through to super.onDestroy()");
   }
}
  • 還有個值得注意的地方就是對 Event.ON_STOP 的處理。在上面的調用圖中我們可以看到,在 onSaveInstanceStateonStop 時都派發(fā)了 Event.ON_STOP 事件,且將狀態(tài)置為了 CREATED。這是因為,在 onSaveInstanceState 后,其實不應該再更新界面了,此時就先派發(fā) Event.ON_STOP 使其狀態(tài)為 CREATED,阻止 ViewModel 更新 UI。同時 onStop 時也需要派發(fā),因為當 Activity 銷毀時,不一定調用 onSaveInstanceState。
2. LifecycleRegistry

LifecycleRegistryLifecycle 的唯一實現類,負責管理 LifecycleOwner 的當前狀態(tài),及接收 Lifecycle 事件后狀態(tài)的流轉,負責添加移除觀察者 LifecycleObserver,并向觀察者通知 LifecycleOwner 當前的狀態(tài)。主要實現了以下的邏輯:

  • addObserver 添加觀察者時,當前的 LifecycleOwner 處于什么狀態(tài),觀察者將一次性收到這個狀態(tài)前的所有事件。比如,在 onPause 時調用 addObserver,由于此時 LifecyclerOwner(也就是 Activity) 處于 STARTED 狀態(tài),因此觀察者將一次性依次收到 ON_CREATEON_START 兩個事件。

  • 我們在實現觀察者時,使用了 @OnLifecycleEvent 注解向 LifecycleRegistery 表示我們關心的事件。其實 LifecycleRegistry 還為我們每個觀察者綁定了狀態(tài)以確保一種有序性:在任意時刻,后添加的觀察者狀態(tài) <= 先添加的觀察者狀態(tài)。也就是,先添加的觀察者會先收到最新狀態(tài)。當然,最終的穩(wěn)態(tài)一定是所有觀察者的狀態(tài)都一致,但是在給每個觀察者派發(fā)事件的過程中,可能會出現各個觀察者狀態(tài)不一致的情況,LifecycleRegistry 會保證上面所說的有序性。

2.1 LifecycleRegistry 的 handleLifecycleEvent 方法 & markState() 方法

看下 handleLifecycleEvent 的源碼:

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    State next = getStateAfter(event);
    moveToState(next);
}

// markState 被 @Deprecated 了,使用 setCurrentState
public void setCurrentState(@NonNull State state) {
    moveToState(state);
}

可以看到,handleLifecycleRegistry 只是多了一步 getStateAfter 方法,根據 (1),這個方法只是根據一個固定的「事件 —— 狀態(tài)」流轉表來獲取當前應該傳入給 moveToState 的狀態(tài)值。

由于 ActivityFragment 有固定的「事件 —— 狀態(tài)」流轉表,因此在 ActivityFragment 的生命周期方法中,源碼使用 handleLifecycleRegistry()。但是當我們自定義了一個 LifecycleOwner 的時候,可能「事件 —— 狀態(tài)」并不需要那么齊全,這時我們只需要在合適的方法中調用 markState() 就可以了。

二、LifecycleOwner

LifecycleOwner 是一個接口,只有唯一的方法 getLifecycle()。它的典型使用方法就是,一個具有生命周期的類,實現該接口,返回該類對應的 Lifecycle 類(最好用現成的 LifecycleRegistry)。然后在該類(比如 ActivityFragment)的生命周期方法中,調用的 LifecycleRegistry.handleLifecycleEvent 方法,來驅動 Lifecycle 狀態(tài)的改變,同時下發(fā)相應事件。在正常的實踐中,LifecycleOwner 是跟 LifecycleRegistry 一起使用的:

class MyActivity : Activity(), LifecycleOwner {

    private lateinit var lifecycleRegistry: LifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

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

    public override fun onStart() {
        super.onStart()
        lifecycleRegistry.markState(Lifecycle.State.STARTED)
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

三、生命周期事件如何在 Activity 和 Fragment 中分發(fā)的?

上一節(jié)我們說到,生命周期事件的分發(fā)是 LifecycleOwnerLifecycleRegistry 配合一起的作用,我們來看看常用的 AppCompatActivity。它繼承自 FragmentActivity,在這個類里我們就發(fā)現了下面的代碼:

/**
 * A {@link Lifecycle} that is exactly nested outside of when the FragmentController
 * has its state changed, providing the proper nesting of Lifecycle callbacks
 * <p>
 * TODO(b/127528777) Drive Fragment Lifecycle with LifecycleObserver
 */
final LifecycleRegistry mFragmentLifecycleRegistry = new LifecycleRegistry(this);

不要誤以為 mFragmentLifecycleRegistry 就是 Activity 所對應的 LifecycleRegistry。它雖然在 Activity 的各個生命周期方法中都有調用 handleLifecycleEvent 方法,但是真正使用它的地方是 FragmentActivity 的內部類 HostCallbacks 中。

mFragmentLifecycleRegistry

HostCallbacks 的實例作為參數傳入了 FragmentController 中:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

這里的 mFragments 其實就是一個代理(可以看 ViewModel 的重建恢復原理#番外),它將 Fragment 所關心的 Activity 的事件等通知給 HostCallbacks 所持有的 FragmentManager,包括 Activity 的生命周期。這樣 Activity 的生命周期就傳給了 Fragment

所以 mFragmentLifecycleRegistry 只是 Activity 將生命周期事件通知給 Fragment 的橋梁。

FragmentActivity 真正的 LifecycleRegistry 應該是通過 getLifecycle() 方法所返回的。jojo

Q: 但是并沒有傳給 Activity 作為 LifecycleOwner 所對應的 LifecycleRegistry。那么 ActivityLifecycleRegistry 是在哪里呢?

我們再往父類看 ComponentActivity。在這里我們找到了:

private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    ReportFragment.injectIfNeededIn(this);
    ...
}

關鍵點就在這個 ReportFragment。我們注意到 ReportFragment.dispatch 中獲取到了 ActivityLifecycle,并調用了 dispatchLifecycleEvent 方法從而將生命周期事件通知到了 ActivityLifecycle

// ReportFragment
static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
    if (activity instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
        return;
    }
    if (activity instanceof LifecycleOwner) {
        Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
        }
    }
}

我們再看 ReportFragment.injectIfNeededIn 方法:

public static void injectIfNeededIn(Activity activity) {
    if (Build.VERSION.SDK_INT >= 29) {
        // On API 29+, we can register for the correct Lifecycle callbacks directly
        activity.registerActivityLifecycleCallbacks(
                new LifecycleCallbacks());
    }
    // Prior to API 29 and to maintain compatibility with older versions of
    // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
    // need to support activities that don't extend from FragmentActivity from support lib),
    // use a framework fragment to get the correct timing of Lifecycle events
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        // Hopefully, we are the first to make a transaction.
        manager.executePendingTransactions();
    }
}

可以注意到:

  • 對于 SDK API ≥ 29 的系統(tǒng),通過直接向 Activity 注冊 LifecycleCallbacks 回調來將生命周期事件通知給 LifecycleRegistry。LifecycleCallbacks 中的每一個回調都會調用上面的 dispatch 方法。
  • 對于 SDK API < 29 的系統(tǒng),則將該 ReportFragment 添加到 ActivityFragmentManager 中。這樣就可以在 ReportFragment 自己的生命周期回調中調用 dispatch 方法。

四、我們使用注解的 Observer 是如何收到生命周期事件的?

注解生成的類

要理解這一節(jié)的內容,最好能夠理解注解處理器的使用。我們知道 APT 在掃描被注解的類后,會調用相應的 processor 來處理這個類,如果有必要,可能會根據這個類的信息來生成一個新的中間類。這個新的中間類就會有很多模板寫法(因此才能夠被生成)。我們來看一個使用注解的類:

static class BoundLocationListener implements LifecycleObserver {
    private final Context mContext;
    private LocationManager mLocationManager;
    private final LocationListener mListener;
    public BoundLocationListener(LifecycleOwner lifecycleOwner,
                                 LocationListener listener, Context context) {
        mContext = context;
        mListener = listener;
        lifecycleOwner.getLifecycle().addObserver(this);
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onLifecycleEvent(LifecycleOwner owner, Lifecycle.Event event) {
        Log.d("jojo", "onLifecycleEvent " + owner.getLifecycle().getCurrentState() + ", event " + event);
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    void addLocationListener() {
        // Note: Use the Fused Location Provider from Google Play Services instead.
        // https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi
        mLocationManager =
                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mListener);
        Log.d("BoundLocationMgr", "Listener added");
        // Force an update with the last location, if available.
        Location lastLocation = mLocationManager.getLastKnownLocation(
                LocationManager.GPS_PROVIDER);
        if (lastLocation != null) {
            mListener.onLocationChanged(lastLocation);
        }
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void removeLocationListener() {
        if (mLocationManager == null) {
            return;
        }
        mLocationManager.removeUpdates(mListener);
        mLocationManager = null;
        Log.d("BoundLocationMgr", "Listener removed");
    }
}

上面的 BoundLocationListener 類拋開業(yè)務邏輯代碼,其實非常簡單:它繼承自 LifecycleObserver,其中的兩個方法 addLocationListenerremoveLocationListener 分別被 @OnLifecycleEvent 注解了不同的生命周期。
我們再來看看 BoundLocationListenerprocessor 處理后所生成的中間類:

public class BoundLocationManager_BoundLocationListener_LifecycleAdapter implements GeneratedAdapter {
  final BoundLocationManager.BoundLocationListener mReceiver;
  BoundLocationManager_BoundLocationListener_LifecycleAdapter(BoundLocationManager.BoundLocationListener receiver) {
    this.mReceiver = receiver;
  }
  @Override
  public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,
      MethodCallsLogger logger) {
    boolean hasLogger = logger != null;
    if (onAny) {
      if (!hasLogger || logger.approveCall("onLifecycleEvent", 4)) {
        mReceiver.onLifecycleEvent(owner,event);
      }
      return;
    }
    if (event == Lifecycle.Event.ON_RESUME) {
      if (!hasLogger || logger.approveCall("addLocationListener", 1)) {
        mReceiver.addLocationListener();
      }
      return;
    }
    if (event == Lifecycle.Event.ON_PAUSE) {
      if (!hasLogger || logger.approveCall("removeLocationListener", 1)) {
        mReceiver.removeLocationListener();
      }
      return;
    }
  }
}
  • 首先從類名上就看得出是由模板拼接出來的,這是方便我們后面說的 Lifecycling 通過反射找到該類。
  • 它實現了一個統(tǒng)一的接口 GeneratedAdapter,其中只有一個方法 callMethods。統(tǒng)一的接口方便 Lifecycling 統(tǒng)一的管理,因為對于 Lifecycling 來說,這些生成類都是 GeneratedAdapter 而已。
  • 該類持有 BoundLocationListener 的實例,并且在 callMethods 方法中,通過條件判斷生命周期事件來調用 BoundLocationListener 的不同方法。
管理注解生成類

分析完注解中間產物類,我們有一個疑問:它是在哪里被初始化,又是在哪里被管理的呢?
我們來看 Observer 被加載到哪里去了。我們知道添加觀察者、移除觀察者的地方是在 LifecycleRegistry 里,在 addObserver 方法中,將傳入進來的 LifecycleObserver 包裝成了 ObserverWithState。我們來看看 ObserverWithState

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;
    ObserverWithState(LifecycleObserver observer, State initialState) {
        // 這里將 observer 又包裝了一遍
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }
    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

Lifecycling 類是我們寫注解時常使用的那種中間 Helper 類,一般來說,它會通過反射等手段來找到我們前面所說的中間產物類(例子中的 BoundLocationManager_BoundLocationListener_LifecycleAdapter 類),管理它的實例、生命周期、方法調用等,并將被注解的業(yè)務類與中間產物類綁定起來。
Lifecycling 的代碼邏輯就比較多了,而且都是用的 Java 反射的特性,我們就不再詳細講解。只說說 lifecycleEventObserver 方法。它會根據我們傳入的 observerClass,然后根據 APT processor 中一樣的規(guī)則來生成中間產物類的類名,然后通過反射得到類的構造函數 Constructor 類,并將其存入到緩存中(方便下次使用時不再反射去找)。最后調用該構造函數,在本例中就是調用 BoundLocationManager_BoundLocationListener_LifecycleAdapter(BoundLocationManager.BoundLocationListener receiver),并返回。返回后就是 ObserverWithState.mLifecycleObserver。當 LifecycleRegistry 分發(fā)事件時,最后會調用到 ObserverWithState.dispatchEvent -> mLifecycleObserver.onStateChanged -> ... -> BoundLocationManager_BoundLocationListener_LifecycleAdapter.callMethods

LiveData

我們知道 LiveData 也是具有生命周期感知能力的,它與 Lifecycle 綁定,只有當生命周期為 STARTEDRESUMED 時,它才會向觀察者發(fā)射數據。同時,在生命周期為 DESTROYED 時,LiveData 也能夠自己釋放。
要實現上面的能力,LiveData需要自己既是數據的發(fā)射者,又是生命周期事件的觀察者。數據觀察者通過 observe(LifecycleOwner, Observer) 方法來將自己與 LiveData 綁定,同時為 LiveData 注入 LifecycleOwner,這樣就使 LiveData 觀察生命周期事件成為了可能。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    // 如果 Lifecycle 處于 DESTROYED 狀態(tài),那么就不會往觀察者發(fā)射數據
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    // 將 owner 和 observer 一起封裝為 LifecycleBoundObserver。
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    // 將 LifecycleBoundObserver 作為觀察者添加進 Lifecycle。
    // 這樣,當有生命周期事件時,會調用 LifecycleBoundObserver 的 onStateChange
    owner.getLifecycle().addObserver(wrapper);
}

從上面我們可以看到,LiveData 自身其實只是一個管理類。它通過操作 LifecycleBoundObserver 來將 LifecycleObserver 關聯起來。我們來看下 LifecycleBoundObserver

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;
    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }
    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }
    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }
    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

對于 Lifecycle 來說,上面的類其實是 LifecycleEventObserver,當 Lifecycle 的生命周期事件需要下發(fā)時,它會調用 LifecycleEventObserver.onStateChanged,在這個方法中我們會看到,如果當前生命周期事件是 DESTROYED,那么會調用 removeObserver 將觀察者從 Lifecycle 中移除掉。否則判斷生命周期是否 ≥ STARTED,如果是的話,則將 LifecycleBoundObserver 的狀態(tài)置為 active,并向開發(fā)者回調 onActive 方法,否則置為 inactive 狀態(tài),并向開發(fā)者回調 onInactive 方法。

LiveData 下發(fā)初值

LifecycleBoundObserver 變?yōu)?active 狀態(tài)時,馬上調用 dispatchingValue 下發(fā)當前值。因此 LiveData 的這個行為有點類比于 RxJavaBehaviorSubject。這個技術實現的關鍵點在于 considerNotify 函數:

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // 這里是關鍵
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

上面的 observer.mLastVersion >= mVersion 決定了的一系列關鍵行為。mVersion 初值為 -1,在 LiveData 每次更新值后,mVersion 都會自增 1。

  • LiveData 中已經有值,此時有一個新的觀察者 observer 訂閱 LiveData。由于observer.mLastVersion 的初值為 -1,因此上面條件不成立,LiveData 向新觀察者 observer 下發(fā)一次當前值。
  • 上面的情況還適合應用因配置改變而導致 ActivityFragment 重建。由于 LiveData 配合使用在 ViewModel 中,因此重建后 ActivityFragment 中的觀察者對于 ViewModel 中的 LiveData 來說依然是新的觀察者。
  • 如果觀察者不被重建,則 LiveDatainactive 變?yōu)?active 時,且 LiveDatainactive 時更新過數據,上面條件不成立,觀察者還是會收到 LiveData 最新的數據。反之,LiveDatainactive 時沒有更新過數據,則觀察者不會收到 LiveData 最近一次的數據。
LiveData 更新值

我們來看看 LiveData.setValue

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

實現上一小節(jié)中的關鍵點就在于 setValue 時,將 mVersion 自增 1 來更新版本號。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容