美文网首页
Lifecycle 解惑

Lifecycle 解惑

作者: 你可记得叫安可 | 来源:发表于2020-09-23 22:58 被阅读0次

Lifecycle & LifecyclRegistry

1. Lifecycler

Lifecycle 是一个抽象类,它的结构很简单:

  • 一系列生命周期事件的枚举定义:EventON_CREATE...ON_DESTROY, ON_ANY
  • 一系列当前所处状态的定义:StateDESTROYEDINITIALIZEDCREATEDSTARTEDRESUMED
  • 添加、移除观察者的 addObserverremoveObserver 方法
    上面的前两点其实是有关联性的,是由 事件的变化 驱动 状态的变化。它们之间的关系如下图所示:
    image.png

我们来看看系统源码中时如何表现上面关系的:
INITIALIZED 是一个初态,因此在 Lificycle 的唯一子类 LifecycleRegistry 的构造函数中就将 Lifecycle 的初始状态设置为 INITIALIZED

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

方法 RegistryLifecycle.handleLifecycleEvent(Lifecycle.Event) 是统一接收 Event 并将 State 状态流转到相应值的地方。

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

我们再看 getStateAfter 方法,其中写死了上图中状态流转的对应关系:

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 生命周期回调的地方,这样就把生命周期回调 -> Event -> State 绑定了起来:

image.png
  • Evnet.ON_CREATE 的发射是在生命周期回调 onCreate 之后,但是 Event.ON_DESTROY 的发射是在生命周期回调 onDestroy 之前。事实上,所有的创建事件都在生命周期回调之后,所有的销毁事件都在生命周期回调之前。
void performCreate(Bundle savedInstanceState) {
   mChildFragmentManager.noteStateNotSaved();
   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()");
   }
   // 发射 lifecycle 事件,更新 lifecycle 状态
   mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}

void performDestroy() {
   mChildFragmentManager.dispatchDestroy();
   // 发射 lifecycle 事件,更新 lifecycle 状态
   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 时都派发了 Event.ON_STOP 事件,且将状态置为了 CREATED。这是因为,在 onSaveInstanceState 后,其实不应该再更新界面了,此时就先派发 Event.ON_STOP 使其状态为 CREATED,阻止 ViewModel 更新 UI。同时 onStop 时也需要派发,因为当 Activity 销毁时,不一定调用 onSaveInstanceState
2. LifecycleRegistry

LifecycleRegistryLifecycle 的唯一实现类,负责管理 LifecycleOwner 的当前状态,及接收 Lifecycle 事件后状态的流转,负责添加移除观察者 LifecycleObserver,并向观察者通知 LifecycleOwner 当前的状态。主要实现了以下的逻辑:

  • addObserver 添加观察者时,当前的 LifecycleOwner 处于什么状态,观察者将一次性收到这个状态前的所有事件。比如,在 onPause 时调用 addObserver,由于此时 LifecyclerOwner(也就是 Activity) 处于 STARTED 状态,因此观察者将一次性依次收到 ON_CREATEON_START 两个事件。
  • 我们在实现观察者时,使用了 @OnLifecycleEvent 注解向 LifecycleRegistery 表示我们关心的事件。其实 LifecycleRegistry 还为我们每个观察者绑定了状态以确保一种有序性:在任意时刻,后添加的观察者状态 <= 先添加的观察者状态。当然,最终的稳态一定是所有观察者的状态都一致,但是在给每个观察者派发事件的过程中,可能会出现各个观察者状态不一致的情况,LifecycleRegistry 会保证上面所说的有序性。

LifecycleOwner

LifecyclerOwner 是一个接口,只有唯一的方法 getLifecycle()。它的典型使用方法就是,一个具有生命周期的类,实现该接口,返回该类对应的 Lifecycle 类(最好用现成的 LifecycleRegistry)。然后在该类的生命周期方法中,调用相应的 LifecycleRegistry.handleLifecycleEvent 方法,来驱动 Lifecycle 状态的改变,同时下发相应事件。在正常的实践中,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 中分发的?

上一节我们说到,生命周期事件的分发是 LifecycleOwnerLifecycleRegistry 配合一起的作用,我们来看看常用的 AppCompatActivity。它继承自 FragmentActivity,在这个类里我们就发现了下面的代码:

/**
 * 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 其实就是一个代理,它将 Fragment 所关心的 Activity 的事件等通知给 HostCallbacks 所持有的 FragmentManager,包括 Activity 的生命周期。这样 Activity 的生命周期就传给了 Fragment但是并没有传给 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

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 的系统,通过直接向 Activity 注册 LifecycleCallbacks 回调来将生命周期事件通知给 LifecycleRegistryLifecycleCallbacks 中的每一个回调都会调用上面的 dispatch 方法。
  • 对于 SDK API < 29 的系统,则将该 ReportFragment 添加到 ActivityFragmentManager 中。这样就可以在 ReportFragment 自己的生命周期回调中调用 dispatch 方法。

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

注解生成的类

要理解这一节的内容,最好能够理解注解处理器的使用。我们知道 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 类抛开业务逻辑代码,其实非常简单:它继承自 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 通过反射找到该类。
  • 它实现了一个统一的接口 GeneratedAdapter,其中只有一个方法 callMethods。统一的接口方便 Lifecycling 统一的管理,因为对于 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 类),管理它的实例、生命周期、方法调用等,并将被注解的业务类与中间产物类绑定起来。
Lifecycling 的代码逻辑就比较多了,而且都是用的 Java 反射的特性,我们就不再详细讲解。只说说 lifecycleEventObserver 方法。它会根据我们传入的 observerClass,然后根据 APT processor 中一样的规则来生成中间产物类的类名,然后通过反射得到类的构造函数 Constructor 类,并将其存入到缓存中(方便下次使用时不再反射去找)。最后调用该构造函数,在本例中就是调用 BoundLocationManager_BoundLocationListener_LifecycleAdapter(BoundLocationManager.BoundLocationListener receiver),并返回。返回后就是 ObserverWithState.mLifecycleObserver。当 LifecycleRegistry 分发事件时,最后会调用到 ObserverWithState.dispatchEvent -> mLifecycleObserver.onStateChanged -> ... -> BoundLocationManager_BoundLocationListener_LifecycleAdapter.callMethods

LiveData

我们知道 LiveData 也是具有生命周期感知能力的,它与 Lifecycle 绑定,只有当生命周期为 STARTEDRESUMED 时,它才会向观察者发射数据。同时,在生命周期为 DESTROYED 时,LiveData 也能够自己释放。
要实现上面的能力,LiveData需要自己既是数据的发射者,又是生命周期事件的观察者。数据观察者通过 observe(LifecycleOwner, Observer) 方法来将自己与 LiveData 绑定,同时为 LiveData 注入 LifecycleOwner,这样就使 LiveData 观察生命周期事件成为了可能。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    // 如果 Lifecycle 处于 DESTROYED 状态,那么就不会往观察者发射数据
    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 的生命周期事件需要下发时,它会调用 LifecycleEventObserver.onStateChanged,在这个方法中我们会看到,如果当前生命周期事件是 DESTROYED,那么会调用 removeObserver 将观察者从 Lifecycle 中移除掉。否则判断生命周期是否 ≥ STARTED,如果是的话,则将 LifecycleBoundObserver 的状态置为 active,并向开发者回调 onActive 方法,否则置为 inactive 状态,并向开发者回调 onInactive 方法。

LiveData 下发初值

LifecycleBoundObserver 变为 active 状态时,马上调用 dispatchingValue 下发当前值。因此 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 下发一次当前值。
  • 上面的情况还适合应用因配置改变而导致 ActivityFragment 重建。由于 LiveData 配合使用在 ViewModel 中,因此重建后 ActivityFragment 中的观察者对于 ViewModel 中的 LiveData 来说依然是新的观察者。
  • 如果观察者不被重建,则 LiveDatainactive 变为 active 时,且 LiveDatainactive 时更新过数据,上面条件不成立,观察者还是会收到 LiveData 最新的数据。反之,LiveDatainactive 时没有更新过数据,则观察者不会收到 LiveData 最近一次的数据。
LiveData 更新值

我们来看看 LiveData.setValue

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

实现上一小节中的关键点就在于 setValue 时,将 mVersion 自增 1 来更新版本号。

相关文章

网友评论

      本文标题:Lifecycle 解惑

      本文链接:https://www.haomeiwen.com/subject/exnuyktx.html