前言
Lifecycle
即生命周期,作为Android开发者,我们对生命周期可太熟悉了,因为我们不仅经常在Activity
、Fragment
的生命周期函数比如onCreate
、onResume
等中做一些逻辑操作;而且组件的生命周期控制不当的话,可能会导致内存泄漏,或者一些无法预想的结果,比如在后台请求网络操作的协程生命周期,要是大于所需要展示UI的界面的生命周期时,就会导致不必要资源浪费。
既然Activity
、Fragment
、协程、ViewModel
、LiveData
,甚至我们常用的Handler
等所有对象,都需要严格管理生命周期,所以管理这些组件的生命周期就非常重要,这里大概能得到2点关于生命周期的需求:
-
给
Activtiy
和Fragment
这种常用的、显示UI的组件,搞一个统一的生命周期表示规则,这样就可以极大地方便开发者。比如我们都希望在页面对用户可见时,才更新UI,对用户不可见时,更新UI是无用功。但是比如
Fragment
就比Activity
多了onCreateView
、onViewCreated
等几个生命周期函数,Fragment
的View
对于可见这个判断就和Activity
不一样了,这就导致开发者完成一个功能,需要对接多个组件。 -
可以获取和监控组件的统一生命周期函数变化。比如不论是
Activity
还是Fragment
,我们都希望在回调其onDestroy()
方法前,释放一些资源,避免造成内存泄漏和资源浪费。
所以Lifecycle
组件就被开发出来了,面对需要对接多个组件的复杂情况,一个有用的方法就是抽象出一层,而Lifecycle
的思想也是如此,让本来开发者需要多个组件的情况下,现在就变成了对接一个组件。
![](https://img.haomeiwen.com/i27208505/958c4bc94437ba1f.png)
如上图所示,有了Lifecycle
后,就可以统一组件的生命周期了,这样我们在开发时就可以面向Lifecycle
这一个组件了,这里我们以使用StateFlow
为例,一般是调用LifecycleOwner
(生命周期持有者)的repeatOnLifecycle
方法:
//该方法为lifecycle-runtime-ktx中方法,用于监听Satate类型的uiState的变化
public suspend fun LifecycleOwner.repeatOnLifecycle(
state: Lifecycle.State,
block: suspend CoroutineScope.() -> Unit
): Unit = lifecycle.repeatOnLifecycle(state, block)
该方法配合StateFlow
使用以达到和使用LiveData
一样的效果,测试代码如下:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 当LifecycleOwner的状态在STARTED及以上时,会触发block执行
// 当ON_STOP事件发生时,block协程会被取消
// 当LifecycleOwner接收到ON_START事件时,会重新执行block
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
uiStateFlow.collect { uiState ->
updateUi(uiState)
}
}
}
}
}
从这里代码注释我们可以看出,这里其实实现了类似LiveData
的效果:会在Activity
可见时绘制UI,在Activity
销毁时取消协程,保证协程的生命周期可控,可以有效地节省资源和防止内存泄漏。
而这个的关键方法repeatOnLifecycle
就是LifecycleOwner
的扩展函数,这里不仅仅Activity
是LifecycleOwner
,Fragment
也是实现该接口,这也就是前面所说的我们开发新功能时只需要面对Lifecycle
这一个抽象层的组件即可。
正文
既然我们想把生命周期给抽象出来,再结合生命周期的作用,这里我们就可以思考一下,应该给抽象为几个部分。在Android中的Lifecycle
框架库中,主要涉及的类如下:
![](https://img.haomeiwen.com/i27208505/071255a53d72441c.png)
这里如果对UML
类图还不熟悉的,可以查看文章:# 效率提升 | UML类图。
从上面UML
类图我们可以知道如下信息:
-
我们常用的
Activity
和Fragment
都是实现了LifecycleOwner
接口,即为生命周期持有者,而LifecycleOwner
是单方法接口,我们可以调用其getLifecycle()
方法返回一个Lifecycle
对象。 -
Lifecycle
是一个抽象类,从其定义的3个方法来分析,主要就2个作用:- 通过添加和移除观察者的观察者模式,我们可以监听
Lifecycle
派发的事件,观察者统一定义为LifecycleObserver
接口。 - 通过
getCurrentState()
方法,我们可以获取当前Lifecycle
的状态,这里的状态State
是一个枚举类型。
- 通过添加和移除观察者的观察者模式,我们可以监听
这也印证了文章刚开始我们抽象Lifecycle
的本意,我们先不急着探究其原理,我们先来思考一下,我们如何使用这些提供的API
。
Lifecycle
的基本用法
第一种用法就是前面所说的,可以监听Lifecycle
所派发的生命周期事件,测试代码如下:
//Activity中代码
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Logger.d("source = $source event = $event")
}
})
}
由于Activity
实现了LifecycleOwner
接口,所以这里可以获取Lifecycle
对象,通过addObserver()
方法可以添加观察者,这里的LifecycleEventObserver
为LifecycleObserver
的子接口:
![](https://img.haomeiwen.com/i27208505/6a4e7964a94fc69e.png)
而这里的生命周期事件就是Event
,对于Activity
来说,其就是对应了其几个生命周期方法,所以上面测试代码中,我们把APP页面打开再关闭,打印如下:
![](https://img.haomeiwen.com/i27208505/cd877c4d4414597d.png)
第二种用法就是前面所说的可以调用getCurrentState()
方法来获取当前Lifecycle
的状态,对于状态State
一共定义了5种枚举,至于为什么是5种,我们等会说原理时细说,这里我们大概和生命周期函数执行完的状态对应起来。
这里我们以LiveData
来举例,LiveData
是具有生命周期感知能力的观察者容器,所以有个特性:使用LiveData
为数据源,做数据驱动来更新UI时,当UI页面不可见时,是不会更新UI的。
既然和生命周期有关,那就必须得用Lifecycle
了,下面是利用LiveData
更新UI:
//Activity中代码
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.uiState.observe(this){
updateUI(it)
}
}
这里调用了LiveData
的observe
方法:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer){
assertMainThread("observe");
//注释1
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
...
}
这里我们可以发现该方法第一个参数是LifecycleOwner
,即生命周期持有者,而我们所熟悉的Activity
就实现了该接口。在注释1处,会判断Lifecycle
的当前状态,如果是DESTROYED
的话,就没必要继续操作了,即当前生命周期组件已经是销毁状态了,完全没必要更新UI了。
这只是LiveData
利用Lifecycle
的getCurrentState()
方法获取状态的一个使用之处,更多关于LiveData
的生命周期感知能力,我们后面介绍LiveData
时再说。
第三种使用Lifecycle
组件的用法就是简化代码,核心思想是分离关注点,让原来需要在Activity/Fragment
的生命周期方法中写的逻辑,给整理到一个生命周期观察者中,这里我们使用官方例子:
class MyActivity : AppCompatActivity() {
//地理位置监听器
private lateinit var myLocationListener: MyLocationListener
override fun onCreate(...) {
//在onCreate方法中,创建监听器,根据监听器更新UI
myLocationListener = MyLocationListener(this) { location ->
// update UI
}
}
public override fun onStart() {
super.onStart()
//判断监听器是否被调用,开启服务
Util.checkUserStatus { result ->
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start()
}
}
}
public override fun onStop() {
super.onStop()
//及时暂停服务,防止资源浪费和内存泄漏
myLocationListener.stop()
}
}
上述代码我相信很多开发者都写过,为了服务能正常创建、启动以及关闭,我们必须保持服务的生命周期和Activity
一致,这样可以防止内存泄漏和避免资源浪费,但是这就导致每个生命周期函数中逻辑过多,这时我们就可以利用Lifecycle
来进行优化。
类似第一种使用方法,我们需要监听Lifecycle
的生命周期改变事件,同时做一些处理,所以我们自定义一个观察者,代码如下:
//继承至DefaultLifecycleObserver
internal class MyLocationListener(
private val context: Context,
private val lifecycle: Lifecycle,
private val callback: (Location) -> Unit
): DefaultLifecycleObserver {
private var enabled = false
init{
lifecycle.addObserver(this)
}
//说明ON_START事件发生,可以看成Activity的onStart函数回调
override fun onStart(owner: LifecycleOwner) {
if (enabled) {
// connect
}
}
fun enable() {
enabled = true
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
// connect if not connected
}
}
//说明ON_PAUSE事件发生,可以看成Activity的onStop函数回调
override fun onStop(owner: LifecycleOwner) {
// disconnect if connected
}
...
}
既然是添加观察者,所以必须是继承至LifecycleObserver
接口,前面说了,这是一个空方法接口,第一种使用方法中,我们是使用了LifecycleEventObserver
,这里我们使用DefaultLifecycleObserver
接口,继承关系如下:
![](https://img.haomeiwen.com/i27208505/fbca2650f5368730.png)
这里的区别显而易见,就是把Event
给细分为了这几个回调函数,同时提供了默认实现。
定义完自定义的观察者后,使用如下:
class MyActivity : AppCompatActivity() {
private lateinit var myLocationListener: MyLocationListener
override fun onCreate(...) {
//只需要在onCreate中调用即可
myLocationListener = MyLocationListener(this, lifecycle) { location ->
// update UI
}
Util.checkUserStatus { result ->
if (result) {
myLocationListener.enable()
}
}
}
}
相比于最开始的代码,我们只需要在onCreate
这一个生命周期函数中进行初始化即可,可以免去在多个生命周期函数中写逻辑,可以简化代码。
第四种用法主要是预防内存泄漏,在代码设计中,有个非常重要的原则是架构和业务分离,就比如我们常见的网络传输协议,TCP已经提供了可靠交付,就不需要我们在业务应用层里面再写关于可靠交付的逻辑了。
在整个Jetpack
组件都是遵循这种原则的,比如我们文章最开始的例子,repeatOnLifecycle()
方法中收集数据的协程,就会当Lifecycle
处于DESTROYED
时自动取消,这样就把合适时机取消协程,防止资源浪费和内存泄漏这个架构设计和业务逻辑给分开了,而不用我们在业务处理时,还考虑这些。
除此之外,还有非常多的小例子,比如这里防止内存泄漏的Handler
:
//这里继承Handler,实现LifecycleEventObserver接口
class LifecycleHandler(val lifecycleOwner: LifecycleOwner) : Handler(),
LifecycleEventObserver {
init {
addObserver()
}
private fun addObserver() {
lifecycleOwner.lifecycle.addObserver(this)
}
//当生命周期持有者状态为DESTROYED时,移除所有消息和回调,保证可以正常被GC回收
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_DESTROY) {
removeCallbacksAndMessages(null)
lifecycleOwner.lifecycle.removeObserver(this)
}
}
}
由于Activity
和Fragment
都是实现了LifecycleOwner
接口,所以所有依赖Activity
和Fragment
的类,都可以采取类似策略,比如Dialog
等,将内存泄漏消灭在架构层逻辑。
看到这里,我相信你会有一些疑问。比如DefaultLifecycleObserver
中的onCreate()
回调是如何和Activity
中的onCreate()
回调保持联动的?有没有先后调用顺?换成Fragment
为生命周期持有者,会不会有什么变化?
带着这些疑问,我们来分析一下其源码。
Lifecycle
解析
既然Lifecycle
是生命周期的抽象,主要用于获取当前生命周期状态以及派发生命周期事件,那么Activity
和Fragment
的生命周期函数个数是不一样的,所以这里需要定义一个更加通用的抽象层。
按照设计,表示Lifecycle
的状态是State
类,它一共有5种状态;而表示状态切换的事件,一共有7个,这里理解起来比较关键,官方有一个图如下:
![](https://img.haomeiwen.com/i27208505/a2ef50f1378c7659.png)
这里我们以Activity
为例,来解释一下这几种State
含义:
-
根据枚举定义,每个枚举值都有一个
int
类型ordinal
值,表示定义枚举的顺序,这个值默认就是0到4
,即State.DESTROYED
最小,State.RESUMED
最大,这也就是状态高低的说法,也是isAtLeast()
方法执行的依据://State的方法 public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; }
比如调用
isAtLeast(STARTED)
为true
,就说明当前Lifecycle
状态为STARTED
或者RESUMED
。 -
我们所熟知的
Activity
的生命周期函数如图:
![](https://img.haomeiwen.com/i27208505/c7f4043ad32ebcbb.png)
这里不算onRestart()
方法一共有6个,但是在前面我们定义的Lifecycle
中State
却没有这么多,所以这里要注意,这里的State
更多的表示是一种状态,而非和生命周期函数一一对应。
- 这里对每一种
State
做细致讲解:-
DESTROYED
:它是最小状态,表示已经销毁的状态,在这个状态的Lifecycle
将不再分发任何生命周期事件Event
,这个状态在Activity
的onDestroy()
调用前到达。 -
INITIALIZED
:表示初始化状态,表示Activity
已经被创建,但是还没有回调onCreate()
方法,即在onCreate()
方法回调前的状态是该状态。 -
CREATED
:表示已创建的状态,注意这种状态不仅仅在Activity
的onCreate()
方法回调后到达,而且在onStop
回调前也是属于该状态,简单来说就是处于CREATED
状态时,组件已经被创建,但是不可见且不可交互。 -
STARTED
:表示可见状态,但是无法交互,所以这种状态在onStart()
回调后和onPause()
回调前到达。 -
RESUMED
:表示处于可交互的running
状态,这也只有在onResumd()
回调后到达。
-
上面我们以Activity
生命周期为例,分析了各种State
的作用,可以总结为下图:
![](https://img.haomeiwen.com/i27208505/d556a1999a0e20dc.png)
这里我们可以知道一个完整的Activity
生命周期,其State
状态是从小到大,再到小,这也是符合我们抽象生命周期的理念:我们更侧重想知道当前Lifecycle
的状态,比如是否可见,是否已经被销毁,方便对应逻辑操作,而生命周期变化的事件,由Event
来定义和派发。
说完了State
,我们来看看其向观察者所派发的Event
事件,这里搞清楚一个设计思路:Lifecycle
的状态切换是由Event
所导致,所以可以认为State
就是一个图中的节点,而Event
就是连接节点的边。
前面我们是以Activity
来说明State
的,其实真实的Event
设计的差不多,也是对应着几种回调函数来设计的,Event
是枚举类,共有6种事件,以及一系列状态切换方法,我们举个简单例子来说明Event
工作流程:
![](https://img.haomeiwen.com/i27208505/cddbaa21ff02d973.png)
所以Event
的定义共如下几种:ON_CREATE、ON_START、ON_RESUME、ON_PAUSE、ON_STOP和ON_DESTROY,至于各自的含义,这里不多说了,就是和生命周期回调函数对应。
这里有个难点,就是Event
中定义的几个方法,配合State
使用,我们来分析一下。
downFrom
方法定义如下:
public static Event downFrom(@NonNull State state) {
switch (state) {
case CREATED:
return ON_DESTROY;
case STARTED:
return ON_STOP;
case RESUMED:
return ON_PAUSE;
default:
return null;
}
}
解释:当从参数state
离开往更低的状态切换,需要分发的Event
。这里的downFrom
函数名我们要分开看,其中down
表示动词,表示向下,而from
就是说明从哪个状态开始,这里结合前面的状态图一起,看代码实现:
- 我们从
CREATED
状态开始,向下降低状态,根据状态图,它下一个状态就是DESTROY
,需要派发ON_DESTROY
事件来完成状态切换。
![](https://img.haomeiwen.com/i27208505/de2b11f45adddf50.png)
- 我们从
STARTED
状态开始,向下降低状态,根据状态图,它的下一个状态是CREATED
,需要派发ON_STOP
事件来完成状态切换。
![](https://img.haomeiwen.com/i27208505/ade24d78ee257e42.png)
类似的方法还有downTo
:
public static Event downTo(@NonNull State state) {
switch (state) {
case DESTROYED:
return ON_DESTROY;
case CREATED:
return ON_STOP;
case STARTED:
return ON_PAUSE;
default:
return null;
}
}
其中down
是动词表示向下,to
表示期望到达某个状态,这里我们需要注意一点:不论是down
,还是后面要说的up
,状态变化只能一步一步来。
即我想从RESUMED
状态,下降到CREATED
状态,根据状态图必须先下降到STARTED
状态,再下降到CREATED
状态,所以我们再看前面downTo
的实现,当期望下降的状态是DESTROYED
时,根据一次只能下降一步的原则,其实它的上一个状态就是CREATED
,所以需要派发ON_DESTROY
事件来完成状态切换。
这里还有类似的upFrom()
和upTo()
方法,我们就不分析了,但是我们要理解其设计思路:这些方法有什么用?
不管是down
还是up
,它的目的都是改变状态State
的值,那我直接改变其值不就好了吗?为什么要知道每一步改变的事件呢?
这就涉及一个思想:永远是事件驱动状态变化,即事件导致状态变化。这里体现为2个方面:
- 对于
Activity
这种生命周期持有者来说,永远都是其自己的onCreate()
方法回调后,收到了ON_CREATE
事件,其状态才变化为CREATED
状态。 - 对于新添加的观察者来说,观察者默认状态是初始化状态,这时假如被观察者已经是
RESUMED
状态,这时需要提升新添加的观察者的状态,从INITIALIZED
提升到RESUMED
,在这个过程中,需要一步一步派发Event
,直到提升到RESUMED
状态。
这2个方面第一个非常好理解,我们来看第二点,第二点其实就对应着Lifecycle
的2个重要函数:addObserver
和removeObserver
。
这里暂时还没有到分析原理的地方,我们可以先说结论,等后面分析原理时再验证一下:
- 对于
addObserver
方法,它是添加一个观察者,当被观察者的状态发生变化时,会通知观察者。
被添加的观察者状态,会被提高到和被观察者一样的状态。比如
LifecycleOwner
的状态是STARTED
,这个刚被添加的观察者,就需要派发ON_CREATE
和ON_START
事件。
- 对于
removeObserver
方法,它是移除一个观察者。
到这里我们仅仅在接口层分析了Lifecycle
的使用,那么接下来就是重点工作了,我们来分析一下Lifecycle
是如何对Activity
和Fragment
进行抽象和封装的。
Lifecycle
原理解析
从前面接口和使用分析,我们知道Lifecycle
是观察者模式,可以用来获取当前Lifecycle
的State
,以及通过观察者来监听Lifecycle
所派发的Event
。
所以这里我们需要知道Lifecycle
是如何进行抽象的,是如何添加/移除观察者,以及如何派发Event
,即
![](https://img.haomeiwen.com/i27208505/83e4959d546e7d1e.png)
这一部分的工作原理,我们先以Activity
为例来解析源码。
话不多说,我们还是先来看看相关类的关系:
![](https://img.haomeiwen.com/i27208505/79fcf8638eece753.png)
这里我们可以发现ComponentActivity
实现了LifecycleOwner
接口,即我们平时使用Activity
就是生命周期持有者。
我们调用getLifecycle()
方法时,其实就是返回ComponentActivity
中定义的LifecycleRegistry
类型的mLifecycleRegistry
成员变量:
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
而且LifecycleRegistry
实现了Lifecycle
接口,所以这里使用了代理模式,所有操作都由这个LifecycleRegistry
来实现。
我们先不去看其源码,我们先来分析一下Activity
生命周期事件是什么时候派发给LifecycleRegistry
的。
原本我以为分发生命周期事件,会在ComponentActivity
的各个生命周期回调函数中调用LifecycleRegistry
方法来派发事件,看了源码发现是利用了ReportFragment
来实现的,调用关系如下:
![](https://img.haomeiwen.com/i27208505/40b22775fecfecdc.png)
上面黄色的Note
表示Lifecycle
的当前State
,由这里我们可以验证最开始说的State
含义:其中INITIALIZED
初始化状态表示组件已经被创建,但是没有收到ON_CREATE
事件,当收到ON_CREATE
事件,状态切换到CREATED
状态。
这里为什么可以使用ReportFragment
的生命周期回调函数中来分发Activity
的生命周期Event
呢?这就涉及了Activity
和Fragment
生命周期函数的调用关系,如下图:
![](https://img.haomeiwen.com/i27208505/9537f0a91f17fd62.png)
虽然这里Fragment
比Activity
多几个生命周期函数,但是丝毫不影响我们使用Fragment
的生命周期来派发其所依赖的Activity
的生命周期事件。
通过简单查看源码,对应关系如下:
-
Activity
的ON_CREATE
事件在Fragment
中的onActivityCreated()
方法中分发。 -
ON_START
、ON_RESUME
、ON_PAUSE
、ON_STOP
和ON_DESTROY
都是由其同名生命周期方法中分发。
这里分发事件的方法就是调用LifeycleRegistry
的handleLifeEvent()
方法,该方法我们后面细说。
说完了Activity
是如何适配Lifecycle
的,主要就是能够正确地、合理地派发Event
给LifecycleRegistry
,我们接着来看一下Fragment
的流程,因为Fragment
有一点不一样,它在派发Event
有2套逻辑。
我们一般使用LiveData
作为观察者容器,在Fragment
的onViewCreated()
方法中进行数据观察和更新UI:
![](https://img.haomeiwen.com/i27208505/4e003ae0615a901b.png)
这里我们使用this
即Fragment
对象作为LifecycleOwner
居然会报错,提醒使用viewLifecycleOwner
作为生命周期持有者,那这里这2个生命周期持有者有什么区别呢?如果强行使用this
会有什么问题呢?
带着问题看源码,就有了探索思路,首先就是Fragment
它是实现了LifecycleOwner
接口的,相关类如下:
![](https://img.haomeiwen.com/i27208505/279e62a30cdad8a3.png)
和Activity
一样,通过getLifecycle
获取的依旧是LifecycleRegistry
实例,工作机制一样,当Fragment
的生命周期变化时,通过调用handleLifeEvent()
来保存和处理事件,我们只需要知道在什么时候会派发事件即可,下面是源码总结:
![](https://img.haomeiwen.com/i27208505/bfbca925d2eec025.png)
上面的代码调用流程再配合文章刚开始说的图,是不是可以完美契合上了!尤其是派发事件和生命周期回调函数的先后问题。
从这里的生命周期回调来看,我们可以得出结论:getLifecycle()
获取的Lifecycle
,其代表Fragment
的生命周期。
那getViewLifecycleOwner()
获取的Lifecycle
有什么区别呢?话不多说,直接看源码,涉及的相关类:
![](https://img.haomeiwen.com/i27208505/641d8e3fa97de034.png)
可以发现这里使用了代理模式,但是代理的是LifecycleOwner
对象,所以这里的核心代码就是FragmentViewLifecycleOwner
的实现,在这里面我们依旧还是利用LifecycleRegstry
来管理和处理Event
,所以我们的关键还是看看在什么时候调用了Event
,总结如下:
![](https://img.haomeiwen.com/i27208505/726ab0878e2e6bff.png)
从这里的调用链和前面Fragment
自己的Lifecycle
做比较,我们可以明显发现ON_START
、ON_RESUME
、ON_PAUSE
和ON_STOP
事件的派发时机和Fragment
自己的Lifecycle
是一样的。
而其他几个Event
的派发就和Fragment
的View
的关系更加密切了,这里也就说明一件事:Fragment
的生命周期和其View
的生命周期是不一样的,getViewLifecycleOwner()
返回的viewLifecycleOwner
,表示的是Fragment
中View
的生命周期。
至于区别,我们可以看一张官方的图:
![](https://img.haomeiwen.com/i27208505/f748815c06db8513.png)
从这张图我们可以得出以下结论:
View
的Lifecycle
比Fragment
的Lifecycle
要短。- 当
Fragment
的Lifecycle
为CREATED
时,View
的Lifecycle
可能还没有创建,即使创建了,也会在View
创建完成后才处于CREATED
状态。 - 当
Fragment
还处于CREATED
状态时,就会调用onDestroyView()
函数,这时View
的Lifecycle
就处于DESTROYED
状态了。
分析完上面结论,我们就可以解决这个问题了:
![](https://img.haomeiwen.com/i27208505/71757c1f4a305efb.png)
为什么这里要使用View
的Lifecycle
而不是选择Fragment
的Lifecycle
。
原因非常简单,也就是我们期望更新UI是根据Fragment
的View
的生命周期来做处理,而不是Fragment
的生命周期,那如果用错了,会导致什么问题呢?
这里涉及LiveData
一个特性:当LifecycleOwner
的Lifecycle
处于DESTROYED
状态时,会自动remove
该LiveData
观察者。
所以这里的uiData
会在owner
处于DESTROYED
时自动移除监听,可以防止内存泄漏,并且只更新可见的有效的UI信息。
这里出问题的场景就是Fragment
切换时,可以把旧FragmentA
加入到回退栈中,并且打开新FragmentB
,这时FragmentA
会执行onDestroyView()
方法,但是不会执行onDestroy()
方法,这时因为Fragment
并没有被销毁;
这里如果使用Fragment
的作为LifecycleOwner
,FragmentA
就不会移除uiData
这个观察者,因为它没有到DESTROYED
状态;这时再按返回键,FragmentB
出栈,FragmentA
又重新显示出来,这时会重新回调onViewCreated()
方法,又会重新添加一遍uiData
这个观察者,导致重复添加观察者。
但是使用viewLifecycleOwner
就不会出现这种情况,根据前面生命周期图可知,当执行到onDestroyView()
方法时,Lifecycle
就处于DESTROYED
状态了,这时可以正常移除观察者。
总结
不知不觉已经写了一万多字了,不得不说,这种优秀的库的源码就是一座宝藏,看源码的过程真的是一个持续学习的过程,不仅仅可以加深理解,更可以学习设计思路、实现思路和方法等。
还是做个总结吧,如下:
- 当人们面对复杂的的问题,一个有用的方法是分层和抽象,所以Lifecycle就是为了统一生命周期,提供一些公共的属性和方法,方便开发者对接。
![](https://img.haomeiwen.com/i27208505/188ae886418a43f9.png)
-
在基本使用前,我们使用
UML
类图来给出了关键类的关系,合理使用UML类图有利于快速构建关系。 -
在基本用法中,我们简单介绍了几种使用,包括:
- 监听Lifecycle所派发的生命周期事件;
- 获取当前Lifecycle状态;
- 根据分离关注点思想来简化代码,把逻辑从散落在生命周期函数中的逻辑给集中一起;
- 还有就是架构和业务分离,合理使用可以预防内存泄漏,比如配合协程、Handler、Dialog等。
-
在Lifecycle解析部分中,我们首先介绍了其中的State和Event,这里需要深刻理解该图:
![](https://img.haomeiwen.com/i27208505/10b424ede0233513.png)
结合图中示意,理解每个State
的含义,以及关键的的downFrom
、upFrom
等方法设计思路和含义。
- 这里我们一直秉承一个思想就是事件驱动状态变化,
LifecycleOwner
实现类比如Activity
,派发Event
驱动Lifecycle
的状态变化,Lifecycle
再派发事件,改变其观察者状态,同时状态变化不能跨级,只能一步一步变化。 - 在
Lifecycle
原理解析部分,先是分析了最常见的组件Activity
是在时候派发Event
的,这部分我们涉及了ReportFragment
的使用和介绍,这种巧妙利用Activity
和Fragment
关系的方式,可以看成是一种hook
,来获取Activity
生命周期回调。 - 实现
LifecycleOwner
的核心是能够正确、合理派发Event
给LifecycleRegistry
。 - 在分析
Fragment
派发Event
中可知,有2个LifecycleOwner
,一个是Fragment
自己的,一个是其View
的,通过分析调用链关系,我们可得如下图:
![](https://img.haomeiwen.com/i27208505/3bbcce3e147315e3.png)
-
通过该图我们需要更加理解
Event
和State
的关系,以及和对应生命周期函数调用的先后关系。同时分析了在Fragment
中使用viewlifecycle
来替代lifecycle
的原因,就是在旧Fragment
入栈出栈,会导致重复添加观察者。 -
在
LifecycleRegistry
原理部分就比较随意了,是保持学习心态来探究的,它是官方提供的Lifecycle
接口的实现类,可以处理多个观察者。- 在构造函数有个值得学习借鉴的点,就是把
Activity
或者Fragment
使用弱引用封装,这种可以有效防止这种重量级的组件发生内存泄漏。 - 在派发事件中,由于要处理多个观察者状态同步和派发,所以这里使用
mHandingEvent
和mNewEventOccurred
这2个flag能避免多次执行,加快效率。 - 在派发事件和添加观察者这2个都是在主线程调用的函数,为了避免出错和效率,这里通过多个flag来确保
sync()
方法只会运行在非嵌套动作的情况下。 - 其次我们学习了
SafeIterableMap
这个数据接口,同时在LifecycleRegistry
中它一直保持非递增的规则,实际上它是由链表实现的Map,支持在遍历时删除和增加。
- 在构造函数有个值得学习借鉴的点,就是把
-
最后就是
ProcessLifecycleOwner
的介绍,主要用于实现app处于前台、后台判断的需求,同时该库使用ContentProvider
是确保在Application
的onCreate()
之前进行初始化。
作者:元浩875
链接:https://juejin.cn/post/7186533178213924923
网友评论