Jetpack之Lifecycle解读

312 阅读7分钟

1. 概述

Lifecycle-aware 组件是Jetpack 的重要组成部分,它不仅提供给我们单独使用,同时也是其他两个组件 ViewModelLiveData 的基础,具体使用请参看官方文档Handling Lifecycles with Lifecycle-Aware Components
。本文旨在分析Lifecycle组件的核心类LifecycleRegistry.java

在Lifecycle未出现之前,要处理生命周期相关的问题,你需要 Activity 中使用过各种 xxxManager.start()、xxxManager.stop(),或者封装过 Android 生命周期对应的接口并给予实现,当然也可以使用优秀的第三方框架,例如RxLifecycle。Google 为降低开发难度,推出 Jetpack并顺便解决了这个问题。

从各种实现方式中,Lifecycle 选择了观察者模式+注解,方便将业务逻辑从 Activity 中抽离出来,通过注解处理自己关心的状态。

2. 实现思路

我们知道生命周期回调在 Activity 中实现,onCreate->...->onDestroy。要达到控制观察者生命周期的目的,Lifecycle 大致结构如下:

  1. 提供一个管理所有 Observer 的类,用于添加、移除、状态流转、分发事件等功能
  2. Activity 需要持有这个管理类来与自身的生命周期产生关联

作为一个开源框架,这个管理类需要考虑到各种情况,使用者可能在任何时候添加、移除 Observer,包括在事件分发的时候递归使用。Lifecycle 中承担这个职责的是 LifecycleRegistry,下面开始分析。(关于整个框架的组织结构可以阅读末尾的参考文章)

3. LifecycleRegistry

3.1 构造器

LifecycleRegistry 的生命周期跟随宿主 Activity ,如果宿主被销毁,那么事件也不必分发;同时 LifecycleRegistry 也需要记录当前的 state 来决定分发什么事件

    // 1. LifecycleRegistry对应的 state,一般而言跟随 Activity
    private State mState;
    // 2. 弱引用,避免泄露
    private final WeakReference<LifecycleOwner> mLifecycleOwner;

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

3.2 State 和 Event

首先看一下官方提供的一张示意图

构成安卓Activity生命周期的状态和事件
图中标示了 5State,6Event,State 之间的流转触发对应的 Event,例如 CREATED 流转至 STARTED 触发 ON_START,表明需要向所有的 Observer 分发 ON_START 事件; RESUMED 流转至 STARTED 触发 ON_PAUSE,表明需要向所有的 Observer 分发 ON_PAUSE 事件。

组件将 StateEvent 定义在 LifecycleRegistry 的父类 Lifecycle.java

    // ON_CREATE < ON_START < ON_RESUME < ON_PAUSE < ON_STOP < ON_DESTROY < ON_ANY
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }
    // DESTROYED < INITIALIZED < CREATED < STARTED < RESUMED
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }

State 流转分为两个方向,姑且将 app 启动(onCreate->...->onResume)定义为正向流转, app 关闭(onResume->...->onDestroy)定义为逆向流程。

3.3 添加 Observer

1.赋予Observer状态

        // 除非在 onDestroy 方法中调用添加,否则将新的Observer标记为初始状态 INITIALIZED
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;

2.解析Observer

        // Observer装饰类,主要维护Observer对应的state以及解析Observer中被注解的方法,以便事件分发时得到调用。
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);

3.避免重复添加,这里可以看到LifecycleRegistry维护了一个Observer列表

        // 用于判断是否重复订阅
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }

4.判断宿主是否被销毁

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

5.判断是否递归调用

        // 1. 判断是否是重入,即下面序号8处中,Observer可能会调用 addObserver方法或者moveToState方法
        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
  1. 计算一个最小的 State,比较对象有前一个观察者的stateLifecycleRegistry#mState以及mParentStates.get(mParentStates.size() - 1)mParentStates先不用管后面再讲
        State targetState = calculateTargetState(observer);
  1. 标记正在添加 Observer
        //自加,表明正在执行一个添加 Observer 的操作
        mAddingObserverCounter++;
  1. 如果正在添加的 Observerstate(一般是INITIALIZED)小于序号6计算出的 targetState,将 Observer流转至 targetState,每次流转会分发对应的事件。
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);// 先不管,后面再讲
            // 分发事件
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();// 先不管,后面再讲
            targetState = calculateTargetState(observer);
        }
  1. 当满足条件时,对整个Observer列表执行state同步。
        // 这里的判定条件让我想了很久,现举个栗子说明一下
        // 现在假设正在添加观察者 A
        // 1. 初始状态下,isReentrance==false
        // 2. 执行到序号7 mAddingObserverCounter++ 后,进入序号8的 while 循环
        // 3. while循环中会分发事件,A接收到这个事件时,可以进行添加观察者 B 的操作,实现递归,再次进入这个方法。
        // 4. 此时条件满足,isReentrance == true,那么在这一个层级调用中,因不满足条件,sync方法不会得到调用。
        // 结语:这里分析了mAddingObserverCounter变化对isReentrance的影响,同理,事件分发中执行moveToState方法,会引起mHandlingEvent的变化。同样影响 sync 的调用。
        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }

小结:

  1. 结合6、8分析,Observer队列中,队首比队尾的state的值大,这在源码注释是有做说明的。
        /**
     * Custom list that keeps observers and can handle removals / additions during traversal.
     *
     * Invariant: at any moment of time for observer1 & observer2:
     * if addition_order(observer1) < addition_order(observer2), then
     * state(observer1) >= state(observer2),
     */
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();
    
  2. 结合5、7、8、9分析,如果事件分发中不存在Observer干扰LifecycleRegistry的行为,sync会很快得到调用;否则要等到这些干扰结束后才在最外层调用中执行sync,大家可以画个表格分析 addObservermoveState方法在内部相互调用的各种情况。

3.4 sync方法

10.判断宿主是否被销毁

        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                    + "garbage collected. It is too late to change lifecycle state.");
        }
  1. 如果满足条件,则执行同步操作
        // 判断是否已同步的标准是:队首和队尾的所标记的的state相同,并且和LifecycleRegistry#mState相同。
        while (!isSynced()) {
            // 1. mNewEventOccurred控制着是否能够进入 sync 方法和控制 sync 内部是否分发事件。如果出现递归调用,mNewEventOccurred==true,上述两种行为都不会执行,直到返回递归栈顶层。
            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;
  1. moveToState(),存在干扰行为时,中途返回,不会调用sync
    private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        sync();
        mHandlingEvent = false;
    }
  1. 即逆向流转,onResume->...->onDestroy
    private void backwardPass(LifecycleOwner lifecycleOwner) {
        //逆序排列,最后添加的Observer最靠前,根据前文的分析,队尾的 state 值最小。
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
                // 即序号11中分析的,如果事件分发中存在递归调用 moveToState 方法,!mNewEventOccurred==false,跳出循环
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            // 外层遍历所有 Observer
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            // 内层流传所有的 State
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));// 后面再讲
                observer.dispatchEvent(lifecycleOwner, event);
                popParentState();
            }
        }
    }

3.5 mParentStates

对于mParentStates,同样是百思不得其解,虽然给了文档说明,但还是太绕了,我们一起看一看。

    // we have to keep it for cases:
    // void onStart() {
    //     mRegistry.removeObserver(this);
    //     mRegistry.add(newObserver);
    // }
    // 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.
    private ArrayList<State> mParentStates = new ArrayList<>();

文档中举了一个例子,说明为什么要引入mParentStates,这里就不去翻译它了,太抽象,我们按照它这个例子走一遍看看有什么样的效果。

分析,大家结合官方示意图和 addObserver 方法的源码会更直观

  1. 执行上面onStart方法前,mRegistry#mState==STARTED,mHandlingEvent = true
        private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        ..
        mHandlingEvent = true;
        sync();
        mHandlingEvent = false;
    }
    
  2. 在所有的事件分发代码两侧都会保存和移除 state 操作,这里保存了观察者 A 流转之前的State==CREATED
                pushParentState(observer.mState);
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
    
  3. A在 onStart 移除自己,不会触发任何回调
  4. 向LifecycleRegistry添加新的 Observer B,执行 addObserver 方法,B 被置为 INITIALIZED,在执行calculateTargetState方法时,比较对象是(1)前一个观察者的state(2)mRegistry#mState==STARTED、(3)mParentStates记录的state==CREATED,最小值是(3)。
  5. 接着执行后面while循环体,B的stateINITIALIZED流转到CREATED,分发ON_CREATE事件。
  6. mHandlingEvent == true;不满足执行sync方法的条件。

结论:如果不利用mParentStates记录记录state,那么第4步得到的就是(2)mRegistry#mState==STARTED,结果就是第5步还会多分发一个ON_START事件。结合源码的注释说明就能理解了,「newObserver should be brought only to CREATED state during the execution of this onStart method」

参考:

Android官方架构组件Lifecycle:生命周期组件详解&原理分析

Android-Lifecycle超能解析-生命周期的那些事儿

Android Architecture Components(一)Lifecycle源码分析

Android arch components 源码分析(2)—— Lifecycle

Android架构之美-Lifecycle