jetpack白盒化之Livecycle如何实现从生命周期到生命周期事件再到通知

149 阅读5分钟

从getLifecycle讲起

查看getLifecycle方法的注释,确定是LifecycleOwner接口定义的,要求实现的,返回一个提供Lifecycle的对象

image.png

那还有谁实现了这个接口?可以说可见的界面如Fragment,ComponentDialog跟ComponentActivity都实现了

image.png

LifeCycle是什么

是抽象类.定义了一个具有Android生命周期的对象.并提供LifeCycleObserver的管理接口。内部包含State和Event概念,将生命周期函数对应成State,生命周期改变会造成State改变,进而触发Event事件,从而被LifecycleObserver接收。

image.png

具体体现就是在Lifycycle接口提供的addObserver跟removeObserver.以及内部枚举类Event跟State,都代表着具备Lifecycle的LifecycleOwner对象的不同状态.

get到的LifeCycle是什么

从上面几个LifecycleOwner接口实现类点击查看,唔,全是LifecycleRegistry.那也就是说提供Lifecycle对象,其实就是LifecycleRegistry.

  • androidx.core.app.ComponentActivity image.png

  • Fragment image.png

  • ComponentDialog image.png

  • androidx.activity.ComponentActivity image.png

  • FragmentViewLifecycleOwner image.png

LifecycleRegistry

作为Lifecycle的实现类,起着添加观察者,响应生命周期事件,分发生命周期事件的作用.

image.png

observerMap字段:观察者容器

内部有一个observerMap的字段,是Map吗?不是,是一个实现了Iterator接口的迭代器,对HashMap进行操作.

image.png

但我们从addObserver跟removeObserver方法的源码可以看到都是由observerMap来完成,将外部传入的LifecycleObserver包装成ObserverWithState,最终交给其内部的HashMap字段保存,说用HashMap来维护的说法其实也可以.

image.png

enforceMainThread字段:线程检测

从构造方法可以得知,还有一个enforceMainThread字段,从字面意思是也能猜到是主线程检测,具体体现在enforceMainThreadIfNeeded方法内,而该方法在其他api操作,如上述addObserver跟removeObserver方法中均会调用进行线程检测,大家知道有这个玩意就行.

image.png

image.png

但是这跟我们要讨论的生命周期到生命周期事件有什么关系? 因为生命周期触发到事件,正是借助LifecycleRegistry对象的handleLifecycleEvent方法来完成.

handleLifecycleEvent方法:事件传递

这里采用ComponentDialog,Fragment跟FragmentActivity为例子.

触发传递关键点

  • 当生命周期变化时,LifeCycleOwner实现类内部由LifecycleRegistry调用handleLifecycleEvent方法为入口调用moveToState到sync方法完成事件接收
  • sync方法调用到backwardPass和forwardPass方法遍历observerMap内保存的ObserverWithState(其实也是取出LifecycleObserver来操作)
  • 遍历环节取出ObserverWithState调用dispatchEvent方法,内部让LifecycleObserver触发onStateChanged方法.

代码走读

生命周期变化触发LifecycleRegistry的handleLifecycleEvent方法传不同生命周期事件

image.png

具体我们一步步点击来看,handleLifecycleEvent方法内先完成线程检测,再开始执行moveToState方法,将生命周期事件的Event内容传入.从上图得知,不同的状态比如onResume,onPause时候都会传不同的Lifecycle.Event事件进来,完成事件处理的环节交给sync方法

image.png

image.png

sync方法内使用backwardPass和forwardPass这两方法最终以正序倒序遍历mObserverMap的内容

遍历内容

通过触发ObserverWithStatedispatchEvent事件,内部会执行LifecycleEventObserver引用分发event.

image.png

image.png

至此,我们知道了当LifecycleOwner出现生命周期变化的时候,是如何通知到LifecycleObserver并触发onStateChange事件的.但这里仍然存在几个问题:

  • 为什么遍历还需要正序倒序?
  • 为什么文章开头所提到的LifecycleOwner没有包含Activity,难道Activity就不能获取到Lifecycle了吗,没法支持addObserver之类的操作了吗?

遍历顺序选择

我们看下判断条件:

image.png

这里需要明确:对比的state,是Lifecycle.State,也就是说DESTROYED < INITIALIZED < CREATED < STARTED < RESUMED.这点由在State中定义的顺序来决定.

image.png

但是State的值取决于前面提到moveToState方法接收Event的值,从Event取State的逻辑告知了生命周期到State的转变 image.png

image.png

判断依据
  • state < observerMap.eldest()!!.value.state

    判断检查当前状态是否小于最早添加的观察者的状态

    如果当前 state 是 STARTED,而最早添加的观察者状态是 RESUMED,那么 STARTED < RESUMED 为 true,这时需要执行 backwardPass,将所有观察者状态降级

  • !newEventOccurred && newest != null && state > newest.value.state

    没有新的事件发生,存在最新添加的观察者的前提下.如果当前 state 是 RESUMED,而最新添加的观察者状态是 STARTED,那么 RESUMED > STARTED 为 true,这时需要执行 forwardPass,将所有观察者状态升级

设计原因

但是这里为什么要有正序和倒序遍历呢? 这涉及到 Lifecycle 状态变化时的一个重要设计原则:绑定通知有序.保证Lifecycle状态变化时 observers 的调用顺序符合以下规则:

  • 当 Lifecycle 状态向上升级时(如 CREATED -> STARTED):应该按照 observers 的注册顺序(正序)调用,这样先注册的 observer 会先收到状态升级的通知,这通过forwardPass来实现.
  • 当 Lifecycle 状态向下降级时(如 RESUMED -> STARTED):应该按照 observers 的注册顺序的反序(倒序)调用,这样后注册的 observer 会先收到状态降级的通知,这通过backwardPass实现
举例

正在使用一个 ComponentActivity:

  • 该Activity处于RESUMED 状态
  • 所有观察者都处于RESUMED 状态
  • state = RESUMED
  • observerMap.eldest()!!.value.state = RESUMED

按Home键以后:

  • 该Activity会调用 onPause()
  • LifecycleRegistry的state变为STARTED
  • 此时:state = STARTEDobserverMap.eldest()!!.value.state = RESUMED
  • 满足 state < observerMap.eldest()!!.value.state 条件

所以会触发backwardPass,将所有观察者状态RESUMED降级到STARTED

从后台切回Activity,Activity恢复前台:

  • 该Activity 会调用 onResume()
  • LifecycleRegistry 的 state 变为 RESUMED
  • 此时:state = RESUMEDobserverMap.newest()!!.value.state = STARTED
  • 满足 state > newest.value.state 条件

所以会触发 forwardPass,将所有观察者状态从STARTED升级到RESUMED

添加新观察者后:满足state > newest.value.state条件

所以会触发forwardPass,将新观察者状态从STARTED升级到RESUMED,确保新观察者能立即响应当前的生命周期状态

该Activity 开始销毁:

  • 调用 onPause(),state 变为 STARTED
  • 满足state < observerMap.eldest()!!.value.state条件
  • 触发backwardPass,将所有观察者状态降级到STARTED
  • 然后调用onStop(),state 变为CREATED
  • 再次满足降级条件,触发 backwardPass
  • 最后调用onDestroy(),state变为DESTROYED

最后一次触发 backwardPass

总结

我们常说的Fragment,ComponentActivity,ComponentDialog里获取的Lifecycle,其实就是LifecycleRegistry

内部提供了hashmap管理保存了观察lifecycle变化的LifecycleObserver

生命周期变化时触发的Event和State变化将遵循向上或者向下的状态遍历,目的是为了实现类似栈的管理,确保观察者有序接收通知

引用