0
点赞
收藏
分享

微信扫一扫

Lifecycle用法与源码分析(手把手教你如何看源码)

逸省 2022-04-17 阅读 85

首先介绍下,什么是Lifecycle。想要知道Google为什么没事要弄一个Lifecycle出来就不得不提及软件开发中一个永恒的话题——解耦。
在android应用程序开发中,解耦很大程度上表现为系统组件(四大组件)的生命周期与普通组件之间的解耦。普通组件在使用过程中通常需要依赖于系统组件的生命周期。有时候,我们不得不在系统组件的生命周期回调方法中,主动对普通组件进行调用或控制。因为普通组件无法主动获知系统组件的生命周期事件。
举个例子,我们经常需要在页面的onCreate方法中对组件进行初始化,在onPause方法中停止组件,而在页面的onDestory方法中对组件进行资源回收工作。这样的工作经常繁琐,会让页面于组件之间的耦合度变高。但又不得不做,因为这可能会引发内存泄露。
我们希望对自定义组件的管理,不依赖于页面生命周期的回调方法。同时,在页面生命周期发生变化时,也能够及时收到通知。这在组件化和架构这几中显得尤为重要,如下图所示:系统组件的生命周期发生变化都会主动通知普通组件。
在这里插入图片描述
为此,Google爸爸提供了LifeCycle作为解决方案。LifeCycle可以帮助开发者创建可感知生命周期的组件。这样,组件便能够在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄漏发生的可能性。Lifecycle不只对Activity/Fragment有用,在Service和App里擦啊中也能大显身手,甚至LiveData也是通过Lifecycle来感知生命周期,可见Google的在下一盘大棋。。。
接下来,我们来看下Lifecycle的用法,如果都不知道怎么用,谈什么分析源码呢?知道该怎么用的读者,可跳过这部分。
用法如下:

  1. 首先,创建一个类继承DefaultLifecycleObserver或者LifecycleObserver

import android.util.Log
import androidx.lifecycle.*
class ApplicationObserver:DefaultLifecycleObserver {

    //在应用程序的整个生命周期中只会调用一次
    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        Log.e("ApplicationObserver","onCreate方法被调用")
    }

    //程序在前台时被调用
    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)
        Log.e("ApplicationObserver","onStart方法被调用")
    }

    //程序在前台被调用
    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        Log.e("ApplicationObserver","onResume方法被调用")
    }

    //程序退到后台被调用
    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        Log.e("ApplicationObserver","onPause方法被调用")
    }

    //程序退到后台被调用
    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        Log.e("ApplicationObserver","onStop方法被调用")
    }

    //永远不会被调用
    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        Log.e("ApplicationObserver","onDestroy方法被调用")
    }
}
  1. 在系统组件中注册该观察者,这里以Activity为例:
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //将观察者与被观察者绑定
        lifecycle.addObserver(ApplicationObserver())
    }
}

完成上面两步即可。运行结果如下:当系统组件的生命周期回调方法被调用的时候,会自动通知ApplicationObserver对应的回调方法。这里留个问题,大家思考下:addObserver是否只能在onCreate方法里调用,如果在onStart、onResume等其他生命周期回调方法中调用会发生什么事呢?
在这里插入图片描述
下面,这是笔者经过几次测试得出的结论,大家可以验证一下:

  • Lifecycle的onCreate方法只会被调用一次,而onDestroy方法不会被调用
  • 当程序从后台回到前台,或者程序被首次打开时,会依次调用Lifecycle的onStart方法和Lifecycle的onResume方法
  • 当程序从前台退到后台(用户按下Home键或任务菜单键),会依次调用Lifecycle的onPause方法和Lifecycle的onStop方法。需要注意:这两个方法会有些延后。这是因为系统需要为"屏幕旋转,由于配置发生变化而导致activity重建"的情况预留一些时间。也就是说,系统需要保证当设备出现这种情况时,这两个方法不会被调用。因为当旋转屏幕时,程序并没有退到后台,只是进入了横/竖屏模式而已。

接下来进入到我们的主题——Lifecycle的源码分析。
我们都知道想要分析源码,需要带着问题去看源码,这样才不会迷失在代码中。或许有些读者认为,我就不带着问题看源码,我就要把源码全部看懂,那你牛逼。说实话除了Google开发人员能完全看懂之外,我认为没几个人能全部看懂,甚至Google开发人员也未必明白,只有写这段代码的人才能算是完全明白,很简单——我们没有这样的场景,就像你维护别人的业务代码,你也会一脸懵逼,之前的人为什么这么写。我们点进addObserver方法,看下源码如何,在这里插入图片描述
发现是个抽象类,我们自然就点进它的实现类去看下:
在这里插入图片描述
他的实现类是一个叫做LifecycleRegistry的类,这个类共有300多行代码,别说看其他方法里的代码,单单是看addObserver方法里的代码,我想就有一群人头晕,心里肯定很不想看。这就是不带着问题看源码的结果。那么,我们的问题是什么呢?
我们想知道Google它是如何做到系统组件的生命周期发生改变就去通知Lifecycle的。
这就是我们的问题,搞明白这个问题,我们看源码的任务就结束了。
针对这个问题,按照我们的猜测,估计就是Google在系统组件的每个生命周期方法里面去调用了Lifecycle的相关方法呗。那我们就点开系统组件的生命周期方法,看是不是如我们所想的那样。
在这里插入图片描述
一开始,笔者查看了onStart、onResuem、onPause、onStop、onDestory这几个生命周期方法,并没有发现任何与Lifecycle有关系的代码。
在这里插入图片描述
在这里插入图片描述
怎么看都没看出和Lifecycle有半毛钱关系。当笔者点开onCreate方法的源码时,总算有点发现。
在这里插入图片描述
mFragmentLifecycleRegistry,多么明显的暗示啊,可见取好名字是多么的重要。我们点进handleLifecycleEvent方法,查看下:
在这里插入图片描述
这里就涉及到一些看源码的技巧了,
一般我们只需盯着入参的走向即可理清源码的主线逻辑,其他的代码我们称之为支线逻辑。
我们看到event参数进入了moveToState方法,那我们看下moveToState方法究竟做了什么事:好像是通过event拿到一个state,如果state与mState一致就什么都不做,不一致就sync(同步)一下。看到这里,我们目前已知的线索有:lifecycle里面有一个event和state,这两个东西有某种对应关系。但是这对解决我们的问题好像没有任何帮助的样子。我们还是不知道:Google它是如何做到系统组件的生命周期发生改变就去通知Lifecycle的。那这样我们再看下父类的oncretae方法做了什么事情:
在这里插入图片描述
有一句代码引起了笔者的注意:ReportFragment.injectIfNeededIn(this);有读者会问为什么不是mSavedStateRegistryController.performRestore(savedInstanceState);我们点进performRestore方法发现里面确实有雨lifecycle相关的源码,但是这还是无法解决我们疑惑?我们还是不知道Google它是如何做到系统组件的生命周期发生改变就去通知Lifecycle的。按照我们的猜测应该是在相关生命周期方法里面去调用Lifecycle的方法才有可能做到的,不然怎么平白无故两个方法会有关系呢?因此,fragment相关的代码更值得我们关注。我们点进injectIfNeededIn方法看下做了什么。
在这里插入图片描述
哦!原来Google这货在创建activity的时候会add进一个空白的fragment,这样当activity的生命周期发生变化的时候fragment的生命周期也会发生变化,我们进一步看下ReportFragment做了什么。
在这里插入图片描述
正如我们所想的那样,在相关的生命周期方法里面都会去dispatch一些event,而我们之前发现event和state有某种关系。
看到这里,我们把手头的线索在捋一下:activity在创建的时候会被add进一个空白的fragment,而activity的生命周期发生变化的时候,fragment的生命周期也会发生变化,在fragment的相关生命周期方法中会dispatch对应的event,event与state又有着某种关系。
既然这样,我们接着看下dispatch里面究竟做了什么事。
在这里插入图片描述
老规矩,我们只需要盯着入参的走向,发现它都进入了一个handleLifecycleEvent方法,既然是if判断,那我们随便挑一个语句看下做了什么即可,为什么呢?回归到我们的问题——我们只需要弄清楚Google它是如何做到系统组件的生命周期发生改变就去通知Lifecycle的,其他的细节可以不需要理会。
在这里插入图片描述

熟悉吗?这不就是我们一开始在oncreate方法里面看到的源码吗?我们还得到一个结论——state与event有某种关系。看来这个关系非常重要,现在我们必须要明白这个关系究竟是什么才有可能解开我们的疑惑。
那我们该从哪里下手呢?自然是从mState开始了,我们发现原来mState是一个enum。那现在我们的疑问来了:这个enum与event有什么关系,与activity的生命周期又有什么关系,与解开我们最初设置的疑惑又有什么关系。
在这里插入图片描述
那我们该如何入手呢?还记得之前的一个sync方法吗?我们之前得到结论——state一致就什么都不做,不一致会sync一下。我们看下sync方法做了什么事情。
在这里插入图片描述
这代码意思,好像是:如果不是同步的,就会去比较下mState与一个map中存储的mState的大小关系,如果大于就forward,小于就backward。那我们就找forwradPass与backwardPass方法看下是什么回事:记住盯着我们的入参。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
onStateChanged是一个待实现的方法。那我们自然就去看下它的实现类了,发现有一堆,那该看哪一个呢?自然是ComponentActivity这个了,我们知道Appcompatactivity是继承这个类的。进去ComponentActivity类,发现在他的构造方法里面有lifecycle的身影。
在这里插入图片描述
addObserver方法,这不是我们添加观察者时用到的方法吗?我们进入addObserver方法一看究竟。发现又是抽象类,进入它的实现类:
在这里插入图片描述
熟悉吗?这不是我们一开始看到的addObserver方法吗?又回到最初的起点。。。当时我们还以无法解答我们疑惑而搁置不看呢?现在没办法了,那我们就看下这个方法究竟干了些什么事?老规矩,盯着入参。
在这里插入图片描述
在这里插入图片描述
发现,来到了一个lifecycleEventObserver方法,那该找哪个if分支看呢?稳妥的方法就是一个个看下去啰。这里笔者介绍一个高效的方法,我们直接看兜底的那一个方法ReflectiveGenericLifecycleObserver。原因很简单,如果代码第一次进入这个方法肯定什么条件都不符合的。看到这个方法名好像和反射有关系,难道Google用了反射,把我们写在LifecycleObserver里面的方法都存起来了?
在这里插入图片描述

在这里插入图片描述
这里有个map,如果map中有就直接return,越来越接近我们的猜想了,一般如果使用了反射都会用一个map把反射的内容都存起来,第二次就直接从map里面拿了。
在这里插入图片描述
呀呀呀!!!这是什么?反射,反射,反射。重要的事情说三遍。Google把反射得到的相关信息存进了mCallbackMap和mHasLifecycleMethods里面了。
至此,我们又得到了一个结论:Google用了反射把我们的写在Lifecycleobsever里面的方法都存了起来。
那我是是否可以大胆猜测一下:我们应该可以找到反射执行的相关的代码。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这不,在onStateChanged方法里面最后确实是执行了反射的相关代码。那这个onStateChanged方法是什么时候执行的?还记得之前的dispatch方法吗?
在这里插入图片描述
我们当时在分析state与event有什么关系时,通过backwardPass方法的指引来到过这个方法。这样就明白了:原来当mState与event中对应的state不一致的时候,就会去调用我们写在lifecycleobserver里面的方法。
到这里,我们在把我们手头上的线索捋一下:
activity在创建的时候会被add进一个空白的fragment,而activity的生命周期发生变化的时候,fragment的生命周期也会发生变化,在fragment的相关生命周期方法中会dispatch对应的event,event与state又有着某种关系。而event中对应的state与mState不一致时,会根据event参数通过反射去执行lifecyclerobserver里面的方法。
到这里,我们的疑惑解开了吗?可以说是解开了:因为我们已经知道Google是怎么去将系统组件的生命周期与Lifecycler关联起来的。但还不够彻底,因为我们不知道event与state究竟是什么关系。
现在我们的疑惑已经变了:我们现在疑惑event与state究竟有什么不为人知的秘密。。。那我们该怎么入手呢?我们注意到dispatch方法里面有一句
State newState = event.getTargetState()代码,我们点进去看下:
在这里插入图片描述

原来,如果event是ON_CREATE和ON_STOP时,对应着State.CREATED;ON_START和ON_PAUSE时,对应着State.STARTED;ON_RESUME时,对应着State.RESUMED;
ON_DESTROY对应着State.DESTROYED。而之前我们看backwardPass方法时,event是通过downFrom方法获取的,我们去downFrom方法看下。

在这里插入图片描述

这不就是状态机模式吗?原来Google维护了一个状态机。现在我们就要搞清楚这个状态机是如何维护状态的。我们看下sync方法。先前提到,如果mState与event所对应的state一致就不做任何操作。例如,当ReportFragemnt类dispatch一个ON_RESUME事件时,如果mState时RESUME状态,说明activity已经是处于onresume状态了,这时候就不需要再去执行lifecycleoberver里面的onresume方法了。如果这时候activity从onresume进入onpause,那么就会mState就会更新为STARTED状态,而此时observer里面的state还是处于RESUMED状态,根据State这个枚举中的定义顺序,STATRTED比RESUME小,就会走backwardPass方法。而backwardPass方法是通过downFrom方法来更新event状态,这样就得到event的值为ON_PAUSE,然后再将event的值传入dispatchEvent方法,这样就会执行observer里面的onpause方法了。
在这里插入图片描述
反之,如果activity从onresume状态回到onstart状态那么就会走forwardPass方法啰。具体读者可以验证下是否如此。
到此,我们的疑惑已经全部解答完毕了。希望这篇文章能够给读者一些帮助。

举报

相关推荐

0 条评论