不看lifecycle源码,认真聊聊它的实现原理
Posted microhex
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不看lifecycle源码,认真聊聊它的实现原理相关的知识,希望对你有一定的参考价值。
1. lifecycle 简介
在我们的日常开发中,使用Activity
和Fragment
产生的内存泄漏问题比比皆是,主要是原因就是这二者存在生命周期,在走完这一辈子的过程中,有些引用一直抓着着Activity
和Fragment
不放,等到它们Destroy
的时候,依旧引用着它们的尸体,导致不能被回收,因为尸体将一直存在于内存中,导致可用内存减少,然后内存泄漏就开始了。当然了,扯远了,Google废了那么大的劲儿开发了 Jetpack
系列,主要是的原因是为了广大开发者能够写出高质量、高性能的代码,今天这里要说的 lifecycle
就是其中的一个优秀代表了。
那么lifecycle
到底有什么用呢?举个很朴实无华的例子,在MVP架构大行其道时,我们的Presenter
层经常需要感知V
层(即Activity
或者Fragment
)的生命周期,在对应的生命周期回调中做些操作,比如在 onDestory
中取消网络请求,关闭数据库等等操作。我们一般的做法是在Activity
的基类中持有 Presenter
的基类,重写Activity
的生命周期回调函数,并在这些回调中调用Presenter
的相应生命周期方法。但是有些组件可能传入的参数并非是Activity
,无法传入一个预定义的类在Activity
相应的生命周期中调用。因为Google
提供了LifeCycle
组件,用于向一个Activity/Fragment
注册生命周期的回调监听。
之所以Google
提供了这种方式,其实就是为了方便开发者无需重写Activity
的生命周期回调方法,直接使用观察者模式对其生命周期进行监听回调。同时Lifecycle
中没有Activity/Fragment
的引用,因此不存在内存泄漏问题。
说了这么多,可能你都没心情看下去,或者一脸懵逼,先来个例子我们试试吧。
2. lifecycle 用法
首先build.gradle
:
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
首先定义一个类继承自androidx.lifecycle.LifecycleObserver
:
class MyCustomObserverBeforeJava8 : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreateX() {
Log.d(TAG,"MyCustomObserver onCreate")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart(owner : LifecycleOwner) {
Log.d(TAG,"MyCustomObserver onStart : $owner")
}
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
fun onResume(owner : LifecycleOwner, event : Lifecycle.Event) {
Log.d(TAG,"MyCustomObserver onAny, $owner, $event")
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
Log.d(TAG,"MyCustomObserver onDestroy")
}
companion object {
private val TAG : String = MyCustomObserverBeforeJava8::class.java.simpleName
}
}
注意到我们的每一个方法上面都有一个注解@OnLifecycleEvent
,注解上面都存在一个Lifecycle.Event
事件,一般都能猜到,被 Lifecycle.Event.ON_CREATE
修饰的方法是在 Activity#onCreate()
方法之后调用的的,依次类推,Lifecycle.Event.ON_STAR
、Lifecycle.Event.ON_DESTROY
等等就不说了,如果不是特别的懂,可以使用代码调试调试:
写好了生命周期监听逻辑,剩下的就是去找我们的Activity
建立联系了:
class MyCustomUI : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG," onCreate method")
}
override fun onStart() {
super.onStart()
Log.d(TAG," onStart method")
}
override fun onResume() {
super.onResume()
Log.d(TAG," onResume method")
lifecycle.addObserver(MyCustomObserverBeforeJava8())
}
override fun onDestroy() {
Log.d(TAG,"onDestroy method")
super.onDestroy()
}
companion object {
private val TAG = MyCustomUI::class.java.simpleName
}
}
看一下,就是这么简单,lifecycle
来自androidx.activity.mLifecycleRegistry
,然后就注册了,我们把MyCustomUI
启动起来:
由于我是在Activity#onResume
方法中注册的,因此输出也应该是这样的:先走完Activity#onCreate() onStart() onResume()
然后再执行 我监听MyCustomObserverBeforeJava8
中的 onCreate() onStart()
方法,可能这个比较神奇,或者有违背于我们的思想。我们被拉进了一个新的微信群,按照道理说,我应该看不到我没加入之前的聊天信息,我是在onResume
方法中注册的,Activity的onCreate()、onStart()
应该在我注册之前就已经被执行过了,理论上我是不应该去接受的,但是这个比较奇怪,也算是lifeCycle
中比较奇怪实现方式了,其实它也有一个书面名字叫“倒灌”,这里我们就不重点讨论了,今天的目的是简单的去了解它,理解它的基本原理即可。
3. lifecycle 原理
看了上面的例子,也许你会和我当初想法类似,为啥加个注解就能感知Activity
或者Fragment
的生命周期啊,我都没没有重写过Activity
的生命周期方法啊,它是怎么做到的呢?我们先不去扒源码,想想在lifecycle
之前,我们所使用过的源码中,是否也有过类似的实现方式呢?
了解Glide
的人肯定都知道,Glide
也可以监听Activity
或者Fragment
的生命周期,这是因为Glide
在with
的时候,添加了一个 空白无界面的SupportRequestManagerFragment
,然后通过监听这个SupportRequestManagerFragment
的生命周期方法,从而来监听ImageView
所在的 Activity
的动作变化,从而在各个生命周期中进行ImageView
的请求和销毁。
那我们可以打印一下我们的 MyCustomUI
中存在的fragments
:
override fun onResume() {
super.onResume()
supportFragmentManager.fragments.forEach { Log.d(TAG, "current fragment : $it") }
}
打印结果:
这里存在一个ReportFragment
,看吧,天下代码都是相互借鉴的,我估计Google
在开发lifecycle
时或多或少应该借鉴了Glide
内置一个无界面 Fragment
的思想,那么我们就来看看这个ReportFragment
在干嘛什么吧:
public class ReportFragment extends Fragment {
private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
+ ".LifecycleDispatcher.report_fragment_tag";
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dispatch(Lifecycle.Event.ON_CREATE);
}
@Override
public void onStart() {
super.onStart();
dispatch(Lifecycle.Event.ON_START);
}
@Override
public void onResume() {
super.onResume();
dispatch(Lifecycle.Event.ON_RESUME);
}
@Override
public void onPause() {
super.onPause();
dispatch(Lifecycle.Event.ON_PAUSE);
}
@Override
public void onStop() {
super.onStop();
dispatch(Lifecycle.Event.ON_STOP);
}
@Override
public void onDestroy() {
super.onDestroy();
dispatch(Lifecycle.Event.ON_DESTROY);
}
}
正与我们所料,它并没有重写Activity
的生命周期方法,但是它重写了Fragment
的生命周期方法,然后通过这个dispatch
方法将生命周期事件分发出去。到此我们的大方向思路就非常明确了,lifecycle
是通过内置的ReportFrament
来监听生命周期,并将生命周期方法回调分发出去。
其实到了这里,你大概就理解了lifecycle
的工作原理了,出去面试的时候,说到这里如果感觉没啥说的,那么就可以往下看,因为思路虽然简单,但是理解起来还是比较费劲的,可能是Google
的源码工程师写的代码比较深入精髓,想要完全去理解还是需要花一些功夫的。
这里我也不带大家去看源码了,这里我想要自己的语言来描述一下这个过程。
人生中我们会经历出生、幼儿期、儿童期、青年期、中年期、老年期、死亡这一系列的周期,同样我们经常使用的Activity
也会经历创建
,onCreate
,onStart
,onResume
,onPause
,onStop
和onDestroy
等生命周期,走完这一短暂又精彩的一生,我们可以看到一张非常经典的Activity生命周期图
:
与人生不可逆的状态相比,Activity
可以重复很多次onStart()
,onResume()
,onPause()
和 onStop()
。如果我们把Activity
的resume
比作人最壮年的时期,那么从onCreate
() -> onStart()
->onResume()
可以看作成一个状态上升;从onResume()
-> onPause()
-> onStop()
可以看作成状态下降,类似于下面的这张图:
首先我们需要明白的一点是,当我们的Activity
执行的某个生命周期方法,只是其生命周期中的一个时间点,而不是时间段。因此在LifeCycle
源码中,把Activity
的整个生命周期分成了7
个时间段:
- 从被创建到调用
onCreate()
之间的时间段,称之为INITIALIZED
; - 从
onCreate()
之后,到onStart()
之前的时间段,称之为CREATED
; - 从
onStart()
之后,到onResume()
之前的时间段,称之为STARTED
; Activity
调用了onResume()
,可以说是一瞬间的事件单,称之为RESUMED
;- 从
onResume()
之后,到onPause()
之前,为了节省资源和逻辑,Google也把这个状态称之为STARTED
; - 从
onPause()
之后,到onStop()
之前,同时也是为节省资源,Google也把这个状态称之为CREATED
; - 最后一种状态,从
onStop()
之后,到onDestroy()
之前,称之为DESTROYED
.
为了便于运算,我们需要将5
个State
进行大小排序:
DESTROYED < INITIALIZED < CREATED < STARTED < RESUMED
理解了上述的前提知识,我们现在需要弄清楚这样一个逻辑,在ReportFragment
的各个生命周期事件中,是如何通过dispatch
不同的Event
,比如
Lifecycle.Event.ON_CREATE
,Lifecycle.Event.ON_START
,Lifecycle.Event.ON_RESUME
,Lifecycle.Event.ON_PAUSE
,Lifecycle.Event.ON_STOP
,Lifecycle.Event.ON_DESTROY
来通知注册的LifecycleObserver
, 从而执行自定义LifecycleObserver
中对应的生命周期方法。
大体的意思可以参考下图:
这里就不卖关子了,直接看LifeCycle
源码怎么做了。
上面我们说过,Activity
的生命周期可以分开两部分去看,一部分是从construct到onResume()
的过程,可以理解为由弱变强的过程,上上图曲线斜率一直为正的过程;另外一个部分是由onResume()到OnDestory()
的过程,可以理解为有强变弱的过程,上上图斜率一直为负的过程。
在LifeCycle
源码中,也是按照这个想法分成两个过程的,上升和下降,它有一个很重要的方法叫getStateAfter(Event)
,位于androidx.lifecycle.LifecycleRegistry#getStateAfter()
下,大概的意思就是按照ReportFragment
分发的LifeCycle.Event
, 来确定当前注册的LifecycleObserver
应该确定在什么周期范围内。
这个getStateAfter
方法的源码就不贴了,直接贴张图了解一下其意思:
对于上升趋势的LifeCycle.Event
:
具体怎么理解呢?
我ReportFragment
分发的一个Lifecycle.Event.ON_CREATE
事件,这时候注册的LifecycleObserver
们的生命周期State
需要到CREATED
阶段; 同样Lifecycle.Event.ON_START
事件,LifecycleObserver
们的生命周期State
需要到STATED
; 最后分发ON_RESUME
事件,LifecycleObserver
们的生命周期的State需要到RESUME
.
同理,对于下降趋势的LifeCycle.Event
,也有相应的图对应:
大致原理和上图差不多,就不细说了。
然后两张图拼接在一起:
按照上面的这张图,我再次把逻辑说一遍,也许第一次看上次会觉得比较乱,但是多体会体会,会觉得LifeCycle
的源码真的写的很艺术:
ReportFragment
会在特定的生命周期方法内分发一个LifeCycle.Event
事件,然后这个事件会在LifecycleRegistry
这个类中被转化成State
状态,然后LifecycleRegistry
会分发给注册的LifecycleObserver
,更新每一个LifecycleObserver
中指向的State
值,使得所有的LifecycleObserver#State
同步,从而达到LifecycleObserver
监听LifeCycleOwner
的生命周期的目的。
当然还有更加细节的逻辑,可能没有讲到,主要是画图我就感觉头晕脑胀了。当然,你看这个图时候,其实每条都有其特殊的意义,upEvent和downEvent不仅仅包含了LifeCycle.Event
转化为State
的逻辑,同时也包含了State
生成LifeCycle.Event
的行为。
什么意思呢?
举个例子,在upEvent的逻辑中,如果我得知当前的State
是CREATED
状态的,那么下一个事件将要指向为LifeCycle.Event.ON_START
事件。这个是干什么用的呢?不扯淡了,就是执行对应注解@OnLifecycleEvent(Lifecycle.Event.ON_START)
修饰的方法使用的,这里有时间再写篇文章聊聊这个问题吧。
对于LifeCycle
的原理,基本上也算是讲了一遍,没有非常深入的讨论源码,因为我认为每个人读源码深入程度都不一样,而且对的源码讲原理也会枯燥和无味,那么我就用自己所理解的语言写出来。当然,这也算是自己的理解,肯定会非常的粗糙和混乱,希望大家可以指出。
以上是关于不看lifecycle源码,认真聊聊它的实现原理的主要内容,如果未能解决你的问题,请参考以下文章
Android arch components 源码分析—— Lifecycle