[Reveal]Lifecycle源码分析

lifecycle_cover_2

Lifecycle是Android Architecture Components组件库的一部分。每个项目的目的一定都是为了解决某个问题,AAC解决的问题就是提供App开发的一些通用组件。而Lifecycle,解决的是在Activity或Fragment之外,响应其生命周期的问题。

不管是使用MVP、MVVM,都会面临一个问题,那就是在Presenter、ViewModel中响应Activity或Fragment的生命周期回调会比较麻烦。Lifecycle就提供了一个几乎无侵入的解决方案。

继续阅读本篇文章默认你已经知道如何使用Lifecycle。

做了什么事

试想一下,假如有一个类A,我们希望A能在Activity的生命周期状态变化时收到通知,比如onResume或者onPause,那我们要怎么实现呢?是不是在Activity的onResume和onPause方法中,调用A类对应的onXxx方法呢?

这应该是最容易想到的一种实现了,实际上Lifecycle的实现逻辑,基本上也是这个模式,就是在Activity的生命周期方法中,调用了某个或者多个“观察者”的对应方法。

可以这么说:Lifecycle实现了观察者模式,在生命周期变化时进行通知。

结构设计

经典的观察者模式,包含Subject和Observer两个角色,Lifecycle组件中,Lifecycle这个接口就扮演了Subject这个角色。除了添加/移除观察者的方法,Lifecycle接口还定义了生命周期的事件状态。具体对应关系看官方的图示。从左向右我们称之为上升,或者前进,反之称为降低或者后退。从数值上看,右侧比左侧大。

lifecycle_state_event

Lifecycle还引入了LifecycleOwner这个接口作为Lifecycle的承载(AppCompatActivity和Support包中的Fragment都实现了这个接口),提供了获取Lifecycle接口实现的方法。通过LifecycleOwner,将Lifecycle的实现和Activity等生命周期组件解耦。可以把LifecycleOwner理解为Lifecycle的“工厂”。

在Lifecycle组件实现的观察者模式中,包含三个角色:LifecycleOwnerLifecycleLifecycleObserver,分别是被观察者工厂,被观察者,观察者。

三者的持有关系是这样的:

1
LifecycleOwner -> Lifecycle -> (n) LifecycleObserver

lifecycle_relationship

无侵入的实现

事实上Lifecycle要解决的问题并不复杂,但是Lifecycle为了提供友好的API,在背后做了非常多的工作,而友好的API的最直观的体现,就是无侵入性。Lifecycle的无侵入性主要体现在以下几个方面:

  • support包中的AppCompatActivity和Fragment都默认实现了LifecycleOwner接口,不需要额外实现。
  • Activity / Fragment生命周期事件的绑定和分发不需要任何额外代码。
  • LifecycleObserver接口不包含任何方法,支持通过注解方式声明要监听的生命周期回调,避免不必要的代码。

因为Lifecycle帮我们实现了LifecycleOwner、Lifecycle两个组件,所以我们才能如此简单的进行监听。

1
2
3
4
5
6
7
8
9
10
// observer
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
Log.d("MyObserver", "onResume")
}
}

// in Activity
lifecycle.addObserver(MyObserver())

下面将按照LifecycleOwner事件分发,LifecycleRegistry的实现,LifecycleObserver的添加的顺序分别介绍Lifecycle的设计。

Activity生命周期事件分发

因为Fragment生命周期的处理方法比较直接,就是在Support包的Fragment类中,在performXxx方法、onXxx方法中进行分发,所以不做赘述。参考源码:Fragment.java。这里我们着重介绍Activity的生命周期回调的处理。

Lifecycle利用Fragment可以同步Activity生命周期的特性,使用ReportFragment这个类来分发Activity的生命周期事件。ReportFragment在Activity创建的时候添加到Activity中,该Activity的生命周期,都将在ReportFragment的onXxx回调方法中分发。

Glide也是利用Fragment来接收Activity的生命周期事件。

ReportFragment是如何被添加到Activity中的呢?

ReportFragment可以通过两种方式添加到Activity中。

  1. 如果Activity继承自ComponentActivity(AppCompatActivity的间接父类),ComponentActivity的onCreate方法中会调用ReportFragment的injectIfNeededIn(Activity)静态方法完成注入。
  2. 如果Activity没有继承自ComponentActivity,Lifecycle使用LifecycleDispatcher类完成ReportFragment的注入。
LifecycleDispatcher?

先留个坑,Lifecycle不仅能监听Activity即组件级别,同时提供进程级别的生命周期监听——ProcessLifecycleOwner。

LifecycleDispatcher和ProcessLifecycleOwner使用相同的方式跟随进程初始化(后文会提到),LifecycleDispatcher在其静态方法init(Context)中,使用Application.registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks)方法向Application中注册了Activity生命周期回调监听器。在监听器的onActivityCreated(Activity, Bundle)回调方法(Activity创建时回调)中,调用ReportFragment.injectIfNeededIn(Activity)方法将ReportFragment注入到Activity中。

小结:

  1. Activity的生命周期事件,通过在Activity创建时注入的ReportFragment进行分发。
  2. ReportFragment注入的位置有两处,ComponentActivity的onCreate方法和LifecycleDispatcher注入的ActivityLifecycleCallbacks内。

默认的Lifecycle实现 LifecycleRegistry

前文提到,Lifecycle是非常关键的一个接口,起到协调观察者和被观察者的作用,实际开发中,我们几乎不需要去实现这个接口,因为Google已经帮我们提供了一个默认的实现类,那就是LifecycleRegistry。

LifecycleRegistry支持添加多个Observer,当Owner状态发生变化时,Owner直接调用LifecycleRegistry的方法,LifecycleRegistry进一步把事件传递给多个Observer。

为了实现Owner到Observer的适配,LifecycleRegistry内部其实就实现了观察者和被观察者的职责。

事实上任何适配器(Adapter),其实就是用不同的接口来分别实现被适配的两边,然后在内部调用两边的接口将数据转换并传递。
比如:现实世界的电源适配器,读卡器。Android框架中ListView、RecyclerView的Adapter等。

  • 观察者的职责:接收外部事件。
  • 被观察者的职责:1. 允许添加观察者。2. 分发事件。

添加观察者的实现涉及到另一个类Lifecycling实现的转换,先留个坑,我们先来看LifecycleRegistry是如何接收事件并传递出去的。

接收&分发事件

LifecycleRegistry接收事件是通过handleLifecycleEvent(Lifecycle.Event)方法,通过前文可以了解到,Lifecycle的状态(State)由事件(Event)驱动进行转换,LifecycleRegister收到事件后,先通过Event得到该Event后的State,然后将所有Observer的State同步到目标State(分发路径上的事件,可能有多个)。

Q:为什么LifecycleRegistry不是直接分发Event而是先计算State,再反推Event进行分发呢?
A:LifecycleRegistry的实现充分考虑了各种情况下事件分发的准确性,主要有两类问题:1. 可重入,2. 一致性。
这里的两次转换主要为了解决第2个问题,为了保证不同生命周期添加的观察者都能正确收到状态变换时的各种事件(一致性),不会漏掉,LifecycleRegistry通过两次转换实现了重放

举个例子解释重放这个概念:一个Observer,O1,在自己的onStart事件中给Activity又添加了一个Observer,O2;这时候O1的onCreate事件和onStart事件都已经回调了,onStart还没有执行完;新添加的O2,会重放这个过程,先执行O2.onCreate,再执行O2.onStart。
如果O2的onStart方法,依赖O2的onCreate方法的结果,重放就能保证逻辑正确。

所有的事件分发,都发生在sync这个方法中,同步的处理包含两种情况:

  • backwardPass:生命周期倒退。分发onPause,onStop,onDestroy事件
  • forwardPass:生命周期前进。分发onCreate,onStart,onResume

LifecycleRegistry使用内部的工具类FastSafeIterableMap作为Observer的集合,FastSafeIterableMap有以下几个特性:

  1. Map,K-V结构存储。
  2. 有序,插入顺序决定保存顺序。支持正向、反向遍历。
  3. 支持在遍历过程中添加、移除元素。(影响LifecycleRegistry的可重入性)

LifecycleRegistry利用FastSafeIterableMap有序的特性,保证添加的Observer按照插入顺序,State从大到小的顺序排列。所以判断同步完成,只需要看第一个Observer和最后一个Observer的状态相等,并且等于LifecycleRegistry的状态。

先看一下Sync方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// happens only on the top of stack (never in reentrance),
// so it doesn't have to take in account parents
private void sync() {
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
+ "new events from it.");
return;
}
while (!isSynced()) {
mNewEventOccurred = false;
// no need to check eldest for nullability, because isSynced does it for us.
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;
}

按照前面说的逻辑,isSynced方法非常简单,只需要判断列表中最大和最小的都和当前状态一致即可。

1
2
3
4
5
6
7
8
private boolean isSynced() {
if (mObserverMap.size() == 0) {
return true;
}
State eldestObserverState = mObserverMap.eldest().getValue().mState;
State newestObserverState = mObserverMap.newest().getValue().mState;
return eldestObserverState == newestObserverState && mState == newestObserverState;
}

backPass

backPass的逻辑是:所以如果第一个Observer的state小于等于LifecycleRegistry的state,所有的Observer都小于等于LifecycleRegistry的state;反之,如果第一个Observer的state大于LifecycleRegistry的state,那可能还有其他的Observer的state大于LifecycleRegistry的state,这时候就让所有state大于LifecycleRegistry的state的Observer进行倒退,同步到LifecycleRegistry的state。

因为LifecycleRegistry中的Observer列表,能确保按照顺序生命周期依次相等或更小。所以backPass要从后往前遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void backwardPass(LifecycleOwner lifecycleOwner) {
// 反向遍历的迭代器
Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
mObserverMap.descendingIterator();
// 如果在分发过程中有新的事件,就终止分发
while (descendingIterator.hasNext() && !mNewEventOccurred) {
Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
// 内部对Observer的封装,记录Observer的状态
ObserverWithState observer = entry.getValue();
// 如果Observer的state比当前state大,调整state(通过分发事件)
// 这里判断是否contains可能是为了兼容在分发过程中Observer被移除的情况,避免不必要的处理。比如Observer的state比当前state大两个级别,那么下面的循环将执行两次,第一次分发事件的处理中,有可能就把Observer移除了;第二次在进入循环,mObserverMap中就不会存在这个entry了。
while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
// 获取下一个事件
Event event = downEvent(observer.mState);
// 兼容重入场景,入栈。这里记录的是observer的目标状态,也就是执行完event后的状态。
pushParentState(getStateAfter(event));
// 分发事件
observer.dispatchEvent(lifecycleOwner, event);
// 兼容重入场景,出栈。
popParentState();
}
}
}

forwardPass

forwardPass刚好相反,如果Observer中,最小的那个比当前state大,就不需要处理;如果最小的不比当前的大,那就需要把比当前state小的Observer的状态前进到当前状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void forwardPass(LifecycleOwner lifecycleOwner) {
// 正向遍历的迭代器,同时支持在遍历过程中删除和添加。
Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
mObserverMap.iteratorWithAdditions();

while (ascendingIterator.hasNext() && !mNewEventOccurred) {
Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
// 内部对Observer的封装,记录Observer的状态
ObserverWithState observer = entry.getValue();
// 同backfowardPass中的逻辑
while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
pushParentState(observer.mState);
observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
popParentState();
}
}
}

添加Observer

Lifecycle提供的Observer接口:LifecycleObserver不包含任何方法,仅仅作为声明、约束使用。当一个LifecycleObserver的实现类通过addObserver方法添加到LifecycleRegistry时,LifecycleRegistry使用Lifecycling工具类创建适配的GenericLifecycleObserver实现类。根据LifecycleObserver的实现方式,有三种可能的解析结果。

1
2
3
4
5
6
7
8
9
10
11
@RestrictTo(RestrictTo.Scope.LIBRARY)
@SuppressWarnings({"WeakerAccess", "unused"})
public interface GenericLifecycleObserver extends LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/

void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
}
解析
  1. 实现了FullLifecycleObserver的类,包装成FullLifecycleObserverAdapter。FullLifecycleObserver接口定义了生命周期的回调方法,FullLifecycleObserverAdapter就是将GenericLifecycleObserver接口的事件,适配成FullLifecycleObserver的onCreate等方法调用。
  2. 只实现了LifecycleObserver接口,通过@LifecycleEvent注解声明回调方法的类。
    1. 编译时生成了实现GeneratedAdapter接口的实现类。Lifecycling通过类型反射获取构造方法,通过构造方法创建CompositeGeneratedAdaptersObserver类的对象,适配GeneratedAdapter。
    2. 如果没有依赖lifecycle-compiler包,或者生成的类被混淆,Lifecycling将利用反射,查找注解并解析方法声明,将其缓存起来。最终创建ReflectiveGenericLifecycleObserver对象,作为GenericLifecycleObserver接口的实现类。具体解析的逻辑在ClassesInfoCache类中,比较直观,这里就不深入了。
添加

GenericLifecycleObserver仅仅声明了分发事件的方法,LifecycleRegistry内部将其包装成ObserverWithState对象,维护单个Observer的状态,以及分发事件。添加Observer之后,首先要做的就是将Observer的状态,同步到LifecycleRegistry的状态,核心逻辑类似前文的forwardPass。这里主要说下前文提到的可重入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@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);

if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}

// isReentrance表示是重入执行,通过mAddingObserverCounter或mHandlingEvent判断。mHandlingEvent是在前文的sync方法前后进行标记的,也就是“在分发事件”。
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
// 计算要同步到的目标状态,是LifecycleRegistry、上一个添加的Observer的状态、上一层被分发事件的Observer的状态。
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}

if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}

可重入这个概念,在并发的话题里也有涉及,常用的synchronize关键字,就是创建了可重入的临界区(可重入锁)。可重入的含义是相同线程在进入一个临界区之后,还可以再次进入该临界区。如果有锁,可重入就意味着允许线程在加锁的情况下重新加锁。

典型场景就是嵌套调用,下面的递归求和的例子,accumulate方法就会重复进入。

1
2
3
4
5
6
public int accumulate(int n) {
if (n == 0) {
return 0;
}
return n + accumulate(n - 1);
}

可重入有什么影响呢?如果一个方法或者代码块是无状态的,不会修改外部变量,那么重入就不会有副作用,但如果重入的方法或者代码块使用,同时修改了外部变量,那么重入进入方法执行时,执行环境就发生了变化,如果不考虑这种变化,就会导致不可预知的错误产生。

LifecycleRegistry对可重入的处理

LifecycleRegistry在处理生命周期事件时,只要涉及到分发事件,都可能出现重入的场景。因为在事件处理方法中,可能添加新的Observer或者移除现有的Observer,对Observer集合的修改,就是修改了外部变量。

LifecycleRegistry通过parentState缓存嵌套调用情况下上层调用时的状态,来保证下层调用方法执行时,要同步到的目标状态,不会超过上层状态,甚至是当上层的Observer已经被移除的情况(如果没有parentState缓存,后添加的Observer的状态就可能比先添加的Observer的状态更早同步到目标状态)。

这里的状态反映到调用者,更多体现在回调方法的调用顺序上。以onStart方法为例,先添加的Observer(A)的onStart方法,一定比后添加的Observer(B)的onStart方法先执行完成。即便是B在A的onStart方法中添加的情况下(A.onStart执行完成后,B.onStart方法才会执行)。

以官方注释里举得例子来说:

1
2
3
4
5
6
7
8
9
// we have to keep it for cases:
// void onStart() {
// mRegistry.removeObserver(this);
// mRegistry.add(newObserver);
// }
// 在这个onStart方法的执行过程中,newObserver的状态仅应该被提升到CREATED。
// newObserver should be brought only to CREATED state during the execution of
// this onStart method. our invariant with mObserverMap doesn't help, because parent observer
// is no longer in the map.

如果没有parentState的控制,newObserver的状态在add方法执行完成后,将变成STARTED,而这时this表示的Observer的状态仅为CREATED,将无法满足添加顺序决定生命周期变化顺序的要求。

这里理解起来可能比较费劲,要达到的目标,就是在任何时刻mObserverMap中前面的Observer的状态,一定要大于等于后面的Observer的状态。sync方法因为在提升状态时从前向后遍历,降低状态时从后向前遍历,所以一定能保证执行过程中的状态要求;可重入的处理主要发生在有新Observer添加的情况。

LifecycleRegistry实现总结

总结一下LifecycleRegistry的实现,LifecycleRegistry的角色是观察者和被观察者之间的适配器,同时实现了接收和分发事件。这部分比较难理解的是对于状态的同步。LifecycleRegistry内部保存了LifecycleOwner当前的状态,并在接收到变化事件时把最新状态同步给所有的Observer;分发过程中考虑到一致性和可重入的问题,分别通过事件-状态-事件转换和parentState解决。

ProcessLifecycleOwner

最后还要提一下的是ProcessLifecycleOwner,ProcessLifecycleOwner实现了进程生命周期的事件分发,通过静态方法get获取LifecycleOwner接口的单例实例。ProcessLifecycleOwner内部同样使用LifecycleRegistry来适配生命周期事件的分发。有意思的设计有两处:无侵入性的绑定和onPause的处理。

无侵入性的绑定

为了在不修改Application的情况下进行绑定,Lifecycle使用ProcessLifecycleOwnerInitializer来初始化ProcessLifecycleOwner,ProcessLifecycleOwnerInitializer继承自ContentProvider,利用ContentProvider会在Application初始时同时初始化的特点,在ProcessLifecycleOwnerInitializer的onCreate方法中,将Application对象绑定到ProcessLifecycleOwner中,就实现了无侵入性的绑定。

前文提到的LifecycleDispatcher和ProcessLifecycleOwner一样,也是在ProcessLifecycleOwnerInitializer类中完成和Application的绑定,进行初始化。

进程onPause事件的处理

ProcessLifecycleOwner的事件来源有两个:

  1. ProcessLifecycleOwner会向ReportFragment中设置一个Listener,通过这个Listener来获取Activity的create、start、resume事件。
  2. 通过ActivityLifecycleCallbacks,监听Activity的onPause和onStop事件。

Activity可能在系统配置发生变化时被重新创建,而重新创建Activity时当前进程的状态应该是不变的。为了避免重新创建Activity时,Activity的onPause事件使得ProcessLifecycleOwner分发错误的onPause和onResume事件。ProcessLifecycleOwner在分发onPause事件之前做了延迟处理。延迟700ms后再分发onPause事件,以及后续的onStop事件。这样只有当Activity被真正退到后台,才会有onPause和onStop事件的分发。

总结

Lifecycle是AAC(Android架构组件)中的重要一环,因为Activity的重要角色,任何架构设计不可避免的要处理Activity/Fragment的生命周期。而其他的AAC组件比如LiveData,ViewModel等,也依赖于Lifecycle对生命周期进行绑定和处理。Lifecycle要做的事情看起来非常简单,但为了满足各种情况,同时提供友好的API,Google的工程师做了很多有趣又很实用的设计。查看Lifecycle组件源码的过程,也是非常有趣和满足的过程。

希望这篇文章能带你一起思考。