Android Jetpack之Lifecycle使用及源码分析

一、前言

关于Android Jetpack是什么不在赘述,不了解的同学可以看看Android架构木木的这篇文章Android Jetpack让Android一飞冲天。

此文章为Android Jetpack系列文章,内容如下:
Android Jetpack之ViewModel使用及源码分析
Android Jetpack之Lifecycle使用及源码分析
未完待续。。。。。。

二、使用Lifecycle意义

通过Lifecycle 组件我们可以轻松的感知Activity或者Fragment的生命周期的变化。在MVP架构中,常规的感知生命周期变化的做法,需要在BaseActicity中实现一个具有生命周期方法的接口,这种做法导致代码的耦合性较强,Lifecycle 的实现则更加优雅。

三、使用方法

1、首先实现一个观察者

public class TestLifecycleObserver implements LifecycleObserver {

    private final static String TAG = "TestLifecycleObserver";

    //注解表示此处监听onCreate的生命周期
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onCreate() {
        Log.v(TAG, "onCreate...");
    }

    //注解表示此处监听onResume的生命周期
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
        Log.v(TAG, "onResume...");
    }

    //注解表示此处监听onDestroy的生命周期
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        Log.v(TAG, "onDestroy...");
    }

}

2、在被观察者中进行注册

public class MainActivity extends Activity implements LifecycleOwner {

    private LifecycleRegistry registry;
    private TestLifecycleObserver testLifecycleObserver = new TestLifecycleObserver();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        registry.setCurrentState(Lifecycle.State.CREATED);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registry.setCurrentState(Lifecycle.State.RESUMED);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        registry.setCurrentState(Lifecycle.State.DESTROYED);
        registry.removeObserver(testLifecycleObserver);
    }

    private void init() {
        registry = new LifecycleRegistry(this);
        registry.addObserver(testLifecycleObserver);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return registry;
    }
}

看到这里有同学可能觉得,这和传统的MVP方式没有太大区别,需要实现LifecycleOwner接口,并且在相应的生命周期方法里面触发对应的方法,所以同样会有耦合,需要自己去控制相应的逻辑。
事实上,在26.0.1版本后的support库中的Activity、Fragment已经为我们实现了LifecycleOwner接口,我们只需要调用addObserver添加观察者,并且在合适的时机解注册即可。之前的版本可以采取以上方式,自己实现LifecycleOwner接口,也可以实现生命周期变化的观察。

四、源码分析

同样我们带着问题来看代码,通过以上的使用方法,我们可能会有如下问题:
1、LifecycleRegistry内部是如何维护观察者的
2、setCurrentState的时候发生了什么
3、LifecycleRegistry初始化时传入了this参数会不会造成内存泄漏

1、LifecycleRegistry的基本结构

先看看LifecycleRegistry中关键的部分,代码如下:

public class LifecycleRegistry extends Lifecycle {
    /**
     * 一个列表,并且可以在遍历期间添加或者删除元素
     * 新观察者的状态一定是小于等于之前的观察者的
     */
    private FastSafeIterableMap mObserverMap =
            new FastSafeIterableMap<>();
    /**
     * 当前状态
     */
    private State mState;
    /**
     * 以弱引用保存LifecycleOwner,防止内存泄漏
     */
    private final WeakReference mLifecycleOwner;
}

//LifecycleRegistry继承自Lifecycle
public abstract class Lifecycle {

    @SuppressWarnings("WeakerAccess")
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }

    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }

}

由于Lifecycle用enum的形式定义了所有State,并且各个状态是按照固定的顺序来变化的,所以State具备了大小和顺序的概念。LifecycleRegistry将事件通知给所有观察者之前,存在一个同步的过程。这个同步的过程中,前面的观察者已经通知到了,后面的观察者还没被通知,于是所有观察者之间的状态就不一致了,各观察者状态之间便产生了大小关系,只有第一个观察者的状态等于最后一个观察者的状态,并且等于LifecycleRegistry中的当前状态mState,才说明状态同步整个完成了。
各个状态的路径变化如下图:


20191129104813484.png

2、观察者的注册及保存

先来看看LifecycleRegistry的addObserver方法

    @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的弱引用,通常是Activity
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }
        //第三步
        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        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--;
    }

大致可以分为三步:
第一步,重新包装观察者生成一个ObserverWithState。LifecycleObserver的关键的生命周期接口实现既可以像上面例子一样通过@OnLifecycleEvent(XXX)注解实现,也可以继承相应的接口实现。所以这个类的主要作用是统一接口回调,并且保存了观察者的状态。
第二步,将封装后的statefulObserver 保存进以原始参数observer为key的map中去,同时判断是否这个observer之前已经添加过了,如果previous 不为null,表示之前已经添加过了,就直接退出流程;如果lifecycleOwner 为null,说明lifecycleOwner已经死亡了,那么也可以直接退出。顺便提一句,LifecycleOwner是作为弱引用传递进来的。
第三步,将新的观察者加进列表之后,通过while循环将它的状态同步到最新的状态mState。upEvent的返回值是传入state的下一个事件,这说明新的观察者仍然会连续收到从INITIALIZED到当前状态之间的所有状态,这里可以理解为是粘性的。

ObserverWithState的代码如下:

static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            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类的lifecycleEventObserver方法来封装观察者,这个方法就是我们前面提到的,将所有观察者的接口适配成一致的。

再来看看观察者的保存列表FastSafeIterableMap,其关键代码如下:

public class FastSafeIterableMap extends SafeIterableMap {

    private HashMap> mHashMap = new HashMap<>();

}

//继承自SafeIterableMap
public class SafeIterableMap implements Iterable> {

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    Entry mStart;
    private Entry mEnd;
    // using WeakHashMap over List, so we don't have to manually remove
    // WeakReferences that have null in them.
    private WeakHashMap, Boolean> mIterators = new WeakHashMap<>();
    private int mSize = 0;

}

我们可以得出以下结论:
1、SafeIterableMap实现了Iterable接口,是可以迭代的。
2、SafeIterableMap并没有实现Map接口,内部维护了一个链表,这样保证了观察者之前的时序性。同时FastSafeIterableMap中有一个HashMap,可以通过key快速查找到对应的节点。
3、mStart代表头节点,mEnd代表尾节点。
4、SafeIterableMap是非线程安全的。
另外这个Map提供了三个迭代器,分别为:
1、升序迭代器AscendingIterator,迭代过程中并不包含新增的元素。
2、降序迭代器DescendingIterator,迭代过程中并不包含新增的元素。
3、迭代器IteratorWithAdditions,迭代过程中包含新增的元素。
AscendingIterator和DescendingIterator的区别在于迭代顺序的不同,两者在创建的一瞬间就已经将头节点和尾节点的指针作为参数传入迭代器了,当迭代进行到mNext == mExpectedEnd或者mExpectedEnd == null时就会结束,所以不包含后续新增的元素,具体细节可以跟跟代码。我们可以看看AscendingIterator的创建过程和迭代过程的关键方法:

public Iterator> iterator() {
        //将当前情况下的mStart头节点和mEnd尾节点传入迭代器
        ListIterator iterator = new AscendingIterator<>(mStart, mEnd);
        mIterators.put(iterator, false);
        return iterator;
}

//迭代器AscendingIterator和DescendingIterator都是继承自它
private abstract static class ListIterator implements Iterator>,
            SupportRemove {
        Entry mExpectedEnd;
        Entry mNext;

        ListIterator(Entry start, Entry expectedEnd) {
            this.mExpectedEnd = expectedEnd;
            this.mNext = start;
        }

        @Override
        public boolean hasNext() {
            return mNext != null;
        }

        @SuppressWarnings("ReferenceEquality")
        private Entry nextNode() {
            if (mNext == mExpectedEnd || mExpectedEnd == null) {
                return null;
            }
            return forward(mNext);
        }

        @Override
        public Map.Entry next() {
            Map.Entry result = mNext;
            mNext = nextNode();
            return result;
        }
}

而IteratorWithAdditions则是在迭代过程中包含了新元素的,它是直接从头节点一直向尾部遍历到结束的,代码如下:

private class IteratorWithAdditions implements Iterator>, SupportRemove {
        private Entry mCurrent;
        private boolean mBeforeStart = true;

        IteratorWithAdditions() {
        }

        @Override
        public boolean hasNext() {
            if (mBeforeStart) {
                return mStart != null;
            }
            return mCurrent != null && mCurrent.mNext != null;
        }

        @Override
        public Map.Entry next() {
            if (mBeforeStart) {
                mBeforeStart = false;
                mCurrent = mStart;
            } else {
                mCurrent = mCurrent != null ? mCurrent.mNext : null;
            }
            return mCurrent;
        }
}

3、更新状态

调用setCurrentState时,真正调用的其实是moveToState方法,moveToState中的核心方法则为sync(),代码如下:

private void sync() {
        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.");
        }
        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 newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
}

//调用isSynced()
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;
}

可以发现,在进行同步时会调用isSynced()方法,其内部通过判断最新和最老的观察者的状态是否都等于当前状态mState来判断是否已经同步完毕。状态往INITIALIZED->RESUMED方向变化时,调用forwardPass方法。状态往RESUMED->DESTROYED方向变化时,调用backwardPass方法。

forwardPass和backwardPass原理是相同的,只是方向不同,直接看forwardPass的代码:

private void forwardPass(LifecycleOwner lifecycleOwner) {
        Iterator> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Entry entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
}

这里出现了我们刚刚提到的迭代器。逻辑也很简单,遍历观察者,逐个通知,upEvent方法的返回值是传入state的下一个事件,这意味着每个观察者收到的回调都是连续的。

4、对于事件嵌套的处理

通过上面的分析,可以发现常规情况下,有以下两种场景来更新状态:
1、新观察者注册进来
2、新状态被设置进来
考虑以下稍微复杂一些的场景:
1、在回调中发送了新的状态
2、在回调中增加了新的观察者

对于第一个场景,其实是通过mNewEventOccurred变量中断当前正在进行的同步,并且以新的状态同步。

对于第二个场景,在添加新的观察者时,有如下代码:

private State calculateTargetState(LifecycleObserver observer) {
        Entry previous = mObserverMap.ceil(observer);

        State siblingState = previous != null ? previous.getValue().mState : null;
        State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
                : null;
        return min(min(mState, siblingState), parentState);
}

parentState的赋值是在执行观察者的回调前,先将观察者当前状态pushParentState压入栈,在回调结束之后,popParentState出栈。
previous表示新的观察者前面的那个观察者,也就是原来的观察队列的队尾,而现在的队尾是新观察者了。可以看出State是取LifecycleRegistry当前状态,previous当前状态,parentState栈顶状态三者的最小值。这样就保证了新的观察者的状态不会大于之前的观察者的状态。

4、观察者的解注册

观察者解注册的逻辑比较简单,代码如下:

@Override
public void removeObserver(@NonNull LifecycleObserver observer) {
        mObserverMap.remove(observer);
}

至此,整个源码分析过程结束。

你可能感兴趣的:(Android Jetpack之Lifecycle使用及源码分析)