原谅我标题党??
Lifecycle系列:
虐面试官系列Lifecyele篇 - (2)源码分析之 Event & State
虐面试官系列Lifecyele篇 - (3)源码分析之注册 & 发送
待完成:
虐面试官系列Lifecyele 篇 - (5)集成Lifecycle的几种方式的源码差别
又是很久很久没写文章了,最近打算写下Android的又一基础知识: Android 官方架构组件系列。打算把相关的知识点都整理写下,所以本系列的主体为Lifecycle.
在虐面试官系列Lifecyele 篇 -(1)基础讲解中,我们讲过三种集成Lifecycle方式,我们上面讲了三种集成方式,其实一个集成方式源码通了,其他都都类似,我们以第一种最最普通的集成方式来讲解(其他的后期有空再补充吧)。
房东类具体实现:LifecycleRegistry类
我们再来看Lifecycle的其他的抽象函数的具体实现,我们使用的又恰好是LifecycleRegistry
类,该类继承了Lifecycle,所以直接查看该类即可 (PS : 对于这个类,会有很长很长的相关代码介绍,因为这个类是核心,没耐心看的也可以跳过):
public class LifecycleRegistry extends Lifecycle {
//'核心属性单个介绍:'
//'加入的LifecycleObserver会被加入到这个Map队列中(Ps:这个数据结构是核心,也会详细讲解)'
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
new FastSafeIterableMap<>();
//'当前的State状态'
private State mState;
//'当前正在添加的Observer的数量'
private int mAddingObserverCounter = 0;
//'可有理解为是否在进行队列同步State(Sync()方法)状态判断值'
private boolean mHandlingEvent = false;
//'是否有新的Event值通知进来'
private boolean mNewEventOccurred = false;
//'这个如果我们是Activity,就是就Activity的实例'
private final WeakReference<LifecycleOwner> mLifecycleOwner;
......
......
......
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
//'我们知道刚开始LifecycleObserver的默认状态是INITIALIZED,
但是假如当前整个LifecycleRegistry的当前状态是DESTROYED,
那我们也就知道了其实已经回不到其他状态了,
我们就业直接把新添加的LifecycleObserver也变成DESTROYED,后续很多逻辑也就走不通了
(就好比Activity已经变成了onDestory了,也不可能在变成其他什么onCraete,onResume状态了,回不去了)'
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
//'我们知道LifecycleObserver是个观察者,我们给队列的观察者发送通知本来没啥,
直接List<LifecycleObserver> 这个队列都可以管理,收到通知,直接遍历队列发送就可以,
但是假如我们现在直接发送ON_RESUME状态,但我们的LifecycleObserver的状态为INITIALIZED,
我们可能希望观察者收到的是ON_CREATE,ON_START,ON_RESUME都能收到,所以我们必须知道当前LifecycleObserver的状态,
然后根据它的状态,和需要改变的最终的状态值,然后一步步的变化过去,然后一步步的发送事件。
所以我们需要知道当前LifecycleObserver的State状态,
就只能再拿一个ObserverWithState类来包裹住State字段和LifecycleObserver'
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
//'这里我们可以看到使用的是putIfAbsent方法存入队列,这个putIfAbsent在讲解这个数据结构的时候我们会讲到,
它不像一般的Map结构,会用新的值覆盖老的值,而是发现有老的值,就直接把已经存的老的值返回。
所以如果我们把传入的LifecycleObserver在队列中找到了的话,
就说明前面就添加过了,现在是重复添加,直接return返回。'
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
return;
}
//'因为使用了弱引用,所以要获取一下当前的LifecycleOwner不为null,不然后面的就都出问题'
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}
//'先看字面意思mAddingObserverCounnter :Adding - Observer - counter 正在添加的LifecycleObserver的数量,
我们可以看到下面有个mAddingObserverCounnter++ ,然后最后整个addObserver()方法执行完了之后,
又会运行mAddingObserverCounter--,所以正常流程是进来一个LifecycleObserver进来添加,
我们会用这个mAddingObserverCounter加一,然后LifecycleObserver整个都被添加完了后,我们就减一,正常添加是没问题,
但是假如正好并发添加多个观察者,这时候可能一个先进行++操作,但是还没有整个addObserver()方法走完,
另外一个也进来添加了,然后这时候我们的mAddingObserverCounter就 !=0 了。'
//'我们再来看mHandlingEvent参数,字面意思:Handle - Event 处理Event事件,默认为false,
它会在sync()方法(PS:sync()可以理解为更新整个LifecycleObserver队列的State并且发送Event事件方法)置为true,然后sync()方法执行完了后置为false
{
mHandlingEvent = true;
sync();
mHandlingEvent = false;
}
所以这个参数我们可以理解为当前是否正好在处理传入的Event事件( PS:也就是 处理传入事件,更新队列,发送通知)
'
//'isReentrance字面意思: is - Reetrance 是否是重入,
所以我们认为同时多个在添加Observer或者同时发送多个Event进来,都算是重入'
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
//'获取目标State值(也可以简单先初步理解为LifecycleRegistry的State的当前值),后面这里我们会具体讲解'
State targetState = calculateTargetState(observer);
//'开始前加一'
mAddingObserverCounter++;
//'当前的加入的观察者的State值,与目标值进行比较,
因为我们刚加入的观察者,State被赋予了DESTROYED或者INITIALIZED
(PS: 还记得我们前面讲的枚举的小知识点吗?就是枚举值的比较那个
聚个例子:比如我们新加的观察者状态是INITIALIZED,也就是数值1,
而目标State是CREATED,也就是2,所以我们的观察者状态就小于当前的目标State了'
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
//'字面意思就知道,改变观察者的状态前,先把它自身的状态存起来'
pushParentState(statefulObserver.mState);
//'dispatchEvent 分发Event,但是里面的具体的参数是根据当前的观察者的状态值的上一步Event(实现一步步提升,一步步分发)'
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
//'改变观察者的状态后,把原来存的状态给删除掉'
popParentState();
//'重新计算一次目标State值'
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
//'我们上面说了,如果没有重入,则更新整个队列(如果有重入,如果我更新一遍队列,同时还要再更新一遍,中间同时更新一个队列出问题不说,也是浪费资源)'
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
//'mAddingObserverCounter参数减一'
mAddingObserverCounter--;
}
}
讲完了注册,我们来看下我们发送事件:
比如我们在我们的Activity的onResume中发送事件:
@Override
protected void onResume() {
super.onResume();
//'1.直接发送State,告诉要跳到这个State状态'
registry.markState(Lifecycle.State.CREATED);
//'2.直接的是Event,然后跳到相应的Event对应的State状态'
registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
复制代码
然后我们的观察者就会收到这个通知了。
我们来看下发送的相关源码:
//'通过第一种方法'
public void markState(@NonNull State state) {
//'直接移动到指定的State状态值'
moveToState(state);
}
//'通过第二种方法'
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
//'通过getStateAfter方法来获取下一个State值(具体其实就是根据我们的State和Event的关系图)'
State next = getStateAfter(event);
//'然后直接移动到指定的State状态值'
moveToState(next);
}
我们继续来看moveToState
:
private void moveToState(State next) {
//'当前的State状态已经和要求变化的State一致,就没必要运行接下去的代码了
(所以你发送多个相同State值,该方法只会执行一次)'
if (mState == next) {
return;
}
//'将当前的值改为要变化的值'
mState = next;
//'还记得这二个参数的意义不?? mHandlingEvent为true说明正在执行sync方法遍历观察者队列进行更新
mAddingObserverCounter说明同时添加了多个观察者
'
if (mHandlingEvent || mAddingObserverCounter != 0) {
//'如果进入是因为mHandlingEvent为true引起的,说明已经在更新队列,当前又有一个新的State发送进来,
那么 1. 没必要去开启一个新的队列更新任务,所以这里会进行return
2. 同时原来的队列更新任务如果正好更新到一半,那么已经更新好的那些观察者其实也已经不是最新的了,
那么这个任务就要重新整个队列全部重新更新一遍,所以需要一个字段在sync()方法的更新队列里面告诉它有新的Event值进来了。
没错,这个字段就是mNewEventOccurred,所以会有mNewEventOccurred = true;
'
//'如果进入是因为mAddingObserverCounter进入,理由与上面类似(因为加入一个观察者后,我们也会执行sync,所以不需要再启动新的,同时用mNewEventOccureed字段告诉已经执行的sync()方法)'
mNewEventOccurred = true;
return;
}
//如果有在执行sync操作,就把mHandlingEvent置为true
mHandlingEvent = true;
sync();
//sync操作结束,置为false
mHandlingEvent = false;
}
我们可以看到sync方法是比较重要的方法,因为起到了更新队列的功效,本来应该是直接看sync方法的源码,既然说了是更新队列,我们先来说下这个队列的数据结构基础知识,然后再回头看我们的sync方法源码,更容易理解。
PS: 这段实在没兴趣的读者,也可以不看.......
看之前如果对数据结构基础不是很了解,强烈建议看我以前
在这里我们既然讲到了注册时候会把新加入的LifecycleObserver加入到队列中,我们具体讲讲这个队列的数据结构:
我们先从字面意思来看,觉得它跟HashMap等数据结构一样,都是Map结尾,而且用法也差不多,都是put(key,value); get(key);
我们来看下HashMap
的基础代码:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {
......
}
可以看到HashMap
实现了Map<K,V>
接口,该接口定义了Map类型的相关方法定义,比如常见的put,get,containsKey,keySet
等方法:
同时我们额外补充下HashMap的相关基础数据结构原理: 漫画:什么是HashMap? 漫画:高并发下的HashMap
我们再来看我们的FastSafeIterableMap
类:
//'可以看名字就知道这个类只是一个(fast - safeIterableMap),所以核心还是后面的SafeIterableMap类'
public class FastSafeIterableMap<K, V> extends SafeIterableMap<K, V> {
......
}
//'SafeIterableMap实现了Iterable接口'
public class SafeIterableMap<K, V> implements Iterable<Map.Entry<K, V>> {
......
}
我们可以看到,SafeIterableMap
它并没有实现Map
接口,倒是实现了Iterable
接口,Iterable
接口是不是感觉马上就有熟悉感了,什么??不知道是啥???
public interface Collection<E> extends Iterable<E> {
......
}
我们的Collection接口就是实现了该接口,Collection就更熟悉了:
PS: 具体Collection的介绍及相关实现类,可以具体看该文章:集合Collection总览,上面图片也引用该文章
这么一说就瞬间熟悉了,因为这个是链表结构的集合,那我们的SafeIterableMap
是不是也是链表结构,答案是对的。
我们来根据代码一步步来看这个数据结构:
'比如我们的Lifecycle的addObserver方法:'
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
//'使用了putIfAbsent方法'
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
......
}
我们来看FastSafeIterableMap
:
public class FastSafeIterableMap<K, V> extends SafeIterableMap<K, V> {
//'内部含有一个HashMap ,等等!不是说是链表吗?
这个HashMap不是用来最后的存储队列的作用,
我们知道链表的缺点是查找元素需要遍历链表来查找,非常耗时。
而我们一些方法比如判断我们队列是否有某个值,或者取某个特定Key的值,如果遍历链表就太慢了
我们就额外在数据添加到队列后,再添加到HashMap中,直接通过HashMap来判断是否有这个值或者获取值,就很快了'
private HashMap<K, Entry<K, V>> mHashMap = new HashMap<>();
//'HashMap额外进行辅助存储,来判断是否有该Key存储过'
@Override
protected Entry<K, V> get(K k) {
return mHashMap.get(k);
}
//'这个方法是重点:'
@Override
public V putIfAbsent(@NonNull K key, @NonNull V v) {
//'通过get方法,在内部这个HashMap中是否存过这个Key和Value'
Entry<K, V> current = get(key);
//如果取出来有值
if (current != null) {
//'直接把取出来的值返回,记住这个put重复的值进来,不会覆盖原来的值,只是把老的值返'
return current.mValue;
}
//'如果没有存过,就内部这个HashMap把Key和Value存入,
但是这个Value不是直接传入的Value,而是通过put()方法,先把这个内容,存到链表结构中,然后再放到HashMap中'
mHashMap.put(key, put(key, v));
return null;
}
@Override
public V remove(@NonNull K key) {
//'先从链表中把这个Key对应的值移除'
V removed = super.remove(key);
//'再在HashMap中把这个值移除'
mHashMap.remove(key);
return removed;
}
public boolean contains(K key) {
//'通过HashMap来判断是否含有某个值'
return mHashMap.containsKey(key);
}
public Map.Entry<K, V> ceil(K k) {
//查看是否包含了这个Key对应的值
if (contains(k)) {
//'获取对应的值,然后取这个值的上一个值(这里可能会有疑惑,别急,后面就会解答)'
return mHashMap.get(k).mPrevious;
}
return null;
}
}
我们看到了,所谓的FastSafeIterableMap
和SafeIterableMap
的区别是,内部多了一个额外HashMap,来帮助我们快速查找元素,从而不用遍历整个队列,节省了时间。
刚我们看到,我们在加入元素的时候:
mHashMap.put(key, put(key, v));
是通过put方法先加入到队列,然后加入到HashMap中,我们来看下put()方法:
protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
//我们new 了一个Entry对象,放入key和value
Entry<K, V> newEntry = new Entry<>(key, v);
//'因为是新加的,所以链表长度也加一'
mSize++;
//'链表结构大家都知道,是一条长的链,所以会有头有尾,
如果最后一个是空的,说明现在这个链表里面没有元素,
所以这个新加入的元素,既是头又是尾'
if (mEnd == null) {
mStart = newEntry;
mEnd = mStart;
return newEntry;
}
//'如果链表中已经有其他元素,则我们原本最后一个的元素就不是最后一个了,
所以先让最后一个元素的下一个指向我们的新元素,然后我们的新元素的前一个指向了原来的最后一个元素,
然后再把mEnd赋值成新的元素。''
mEnd.mNext = newEntry;
newEntry.mPrevious = mEnd;
mEnd = newEntry;
return newEntry;
}
没错,有些人可能会一脸懵逼,没关系,我已经为大家准备了图片,不怕大家不会。
首先我们知道Entry对象里面是怎么样的(其实就是Map里面我们经常看到的Entry对象):
static class Entry<K, V> implements Map.Entry<K, V> {
//'Key 属性'
final K mKey;
//'Value属性'
final V mValue;
//'下一个Entry的属性'
Entry<K, V> mNext;
//'上一个Entry的属性'
Entry<K, V> mPrevious;
......
......
......
}
换成图片就是这样:
然后这些Entry怎么连在一起呢?如下图所示这样:
是不是这样就一下子理解了。
所以我们刚在的添加Entry的相关代码就能理解了。
同时最近学了做动态动画,以后用来写博客就可以越来越顺手了,比如下图的链表删除元素(gif倒过来就是添加元素):
我们说了往数据结构添加了元素,我们再来说说遍历队列。 虽然我们的这个数据结构,没有直接继承Map
,看我们看到它实现了迭代器,所以HashMap
怎么遍历数据来着:
//获取迭代器
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
//判断迭代器是否有下一个元素值
while(it.hasNext()){
//从迭代器中取出元素值
Map.Entry<String, String> entry = it.next();
System.out.println("key= "+entry.getKey()+" and value= "+entry.getValue());
}
所以我们的这个观察者队列,也是会有相关获取迭代器方法:
//'正序迭代器'
@NonNull
@Override
public Iterator<Map.Entry<K, V>> iterator() {
ListIterator<K, V> iterator = new AscendingIterator<>(mStart, mEnd);
mIterators.put(iterator, false);
return iterator;
}
//'倒序迭代器'
public Iterator<Map.Entry<K, V>> descendingIterator() {
DescendingIterator<K, V> iterator = new DescendingIterator<>(mEnd, mStart);
mIterators.put(iterator, false);
return iterator;
}
//'和上面二个最大的区别是,在迭代过程中,有新的元素被加进来,也可以遍历到'
public IteratorWithAdditions iteratorWithAdditions() {
IteratorWithAdditions iterator = new IteratorWithAdditions();
mIterators.put(iterator, false);
return iterator;
}
复制代码
本来还想长篇的继续分析,但是后来看到其他博主有写的该数据结构很不错的文章:
Android 源码系列之【二十一】从源码的角度深入理解SafeIterableMap
所以配合我上面讲的基础,外加这篇文章,基本对该数据结构就能熟练掌握了。
我们具体来看更新队列的过程:
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;
//'当前实际的mState状态值比队列头的状态小,说明队列的状态值太大了,要后退变小
( 为什么比较队列头,后面会说明)'
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
//'进行后退操作'
backwardPass(lifecycleOwner);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
/**
'
mNewEventOccurred还是false,没有变为true,
(如果是true了,说明有新的Event事件传入,那么这次更新也可以先结束了)
&&
当前实际的mState状态值比队列尾的状态大,说明队列的状态值太小了,要前进变大
( 为什么比较队列头,后面会说明)
'
**/
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
//'进行前进操作'
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
//'判断是否同步完成方法:'
private boolean isSynced() {
//'队列里面观察者数量为空,当然就认为同步完成,返回true'
if (mObserverMap.size() == 0) {
return true;
}
//'队列头的的观察者当前的State状态'
State eldestObserverState = mObserverMap.eldest().getValue().mState;
//'队列尾的的观察者当前的State状态'
State newestObserverState = mObserverMap.newest().getValue().mState;
/**
'队列头与队列尾相同,说明整个队列都一致了'
&&
'队列头与LifecycleRegistry的最新的State状态一样'
('说明整个队列里面的观察者状态都更新到了最新的State值,也就说明同步完成了')
**/
return eldestObserverState == newestObserverState && mState == newestObserverState;
}
复制代码
为什么我们都判断需要后退操作了,还需要重新去判断是否需要前进操作,而不是直接if(后退){xxxxxxx; return}
????
我们为什么后退操作和前进操作时候拿队列里面的元素进行比较,二个比较的元素方向是相反的??
具体看前进操作和后退操作的具体源码(基本一样举一个源码即可):
private void backwardPass(LifecycleOwner lifecycleOwner) {
Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
mObserverMap.descendingIterator();
//'因为我们的后退操作是从队列头开始,往队列尾更新的,
所以迭代器是从头到尾的(前进操作则相反)'
while (descendingIterator.hasNext() && !mNewEventOccurred) {
Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
ObserverWithState observer = entry.getValue();
while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
Event event = downEvent(observer.mState);
pushParentState(getStateAfter(event));
//'调用ObserverWithState的dispatchEvent方法进行事件分发'
observer.dispatchEvent(lifecycleOwner, event);
popParentState();
}
}
}
static class ObserverWithState {
State mState;
GenericLifecycleObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
//'可以看到我们的Observer传入后,实际上通过Lifecycling.getCallback方法再次处理后返回了一个新的Observer'
mLifecycleObserver = Lifecycling.getCallback(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
//'获取Event事件对应的State值'
State newState = getStateAfter(event);
//'与当前的最新的mState进行比较,取最小值'
mState = min(mState, newState);
//'调用具体的真正的观察者(或者是适配器观察者ApdaterObserver)的onStateChanged方法进行回调通知'
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
到这里我们已经知道了,是调用了我们封装的ObserverWithState对象里面的mLifecycleObserver
的onStateChanged
方法,而这个mLifecycleObserver
是把我们addObserver
时候传入的我们自己的Observer
通过Lifecycling.getCallback
方法再次处理后返回了一个新的Observer
。说明我们传入的不同的Observer
,返回的这个回调的mLifecycleObserver
不同,下一篇我们会看到底有哪些不同的观察者。
本文我们介绍了具体注册观察者和发送事件的相关源码。