Android-Lifecycle分析

149 阅读10分钟

0.前言

文本先讨论Lifecycle出现之前开发中的一些问题,通过对比说明Lifecycle的好处。之后着重讲述Lifecycle中状态与事件的关系,简单说了一下LiveData依赖Lifecycle实现的特性,最后分析了Lifecycle的工作流程。

1.Lifecycle之前的世界

百度翻译: Lifecycle—生命周期

正如它的名字,Lifecycle是Google为了帮助开发者更好更方便的利用Activity或Fragment生命周期开发的的组件。

在没有Lifecycle之前,处理Activity或Fragment生命周期是一个头疼的问题。

生命周期的情况多比较复杂,Activity与Fragment它们两个之间有千丝万缕的联系但是又不完全一致,所以在开发时可能会考虑很多细节

Lifecycle是在开发者与Activity和fragment之间建立的一个抽象层,Lifecycle将Activity和fragment的生命周期API简化抽象。

使得开发者在开发各种组件时如果有用到生命周期,不需要去和Activity或Fragment打交道 。

不需要开发者去扣细节,扣顺序。开发人员只需要关注Lifecycle即可。

简而言之,Lifecycle用来感知Activity和Fragment的生命周期状态变化。在Android开发中定义的大多数组件都需要感知组件的生命周期,比如:轮播图,播放器等等。

在没有Lifecycle之前这一类组件会暴露出对应的生命周期方法,比如:onResume,onPause。在Activity或Fragment对应的生命周期中调用。

乍一看没有问题,但在真实情况下,可能会有很多组件需要响应Activity生命周期,会导致Activity的生命周期中存在大量业务代码,难以维护。

如下代码:

class MainActivity : AppCompatActivity() {
    private lateinit var banner: Banner
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        banner = Banner(this);
    }
    override fun onResume() {
        super.onResume()
        banner.start()
    }

    override fun onStop() {
        super.onStop()
        banner.stop()
    }
}

class Banner(private val context: Context) {

    fun start() {
    }

    fun stop() {
    }
}

2.Lifecycle之后的世界

自定义的组件接入Lifecycle之后就会拥有感知Activity生命周期的能力,则可以将控制生命周期的代码收归与组件内部,自动调整状态,无需Activity参与。如下代码:

  1. MainActivity 的代码很简单,初始化Banner,Banner与lifecycle关联
  2. Banner所有的逻辑都在内部实现,外部调用无需关注
class MainActivity : AppCompatActivity() {
    private lateinit var banner: Banner
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        banner = Banner()
				lifecycle.addObserver(banner)
    }
}

class MainFragment : Fragment() {
    private lateinit var banner: Banner
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        banner = Banner()
				lifecycle.addObserver(banner)
    }
}

internal class Banner() : DefaultLifecycleObserver {

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        start()
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        stop()
    }

    private fun start() {

    }

    private fun stop() {

    }

}

通过对比可以总结使用Lifecycle好处:

  1. lifecycle的使用无论是在Activity 或 Fragment中都是一致的,没有任何改变,无需关注两者的生命周期的异同点。
  2. 能够让三方组件在其内部随时拿到Activity的生命周期,执行自身逻辑,减少外部调用,降低代码复杂度
  3. 因为所有代码都在三方组件内部,调试更方便,符合职责单一原则

3.Lifecycle的事件与状态

如图所示:

  1. 整个组件的结构还是非常简单的
  2. LifecycleObserver 观察 Lifecycle 从而得到 LifecycleOwner 的生命周期状态 和 生命周期切换产生的事件
  3. Lifecycle基于LifecycleObserver 的生命周期是从LifecycleOwner得到的
  4. LifecycleObserver 与 LifecycleOwner 没有直接关系

Untitled.png

上面提到**状态(States)事件(Events)**是Lifecycle核心概念

Lifecycle把Activity和fragment的生命周期抽象成五个状态:已初始化,已销毁,已创建,已开始,已恢复。对于开发者来说,Activity 或 Fragment只会在这五种状态来回切换,切换的过程中会发出事件。

如下图:

  1. initialized 切换到 created 状态 发送事件 onCreate
  2. created 切换到 started 状态 发送事件 onStart
  3. started 切换到 resumed 状态 发送事件 onResume
  4. resumed 切换到 started 状态 发送事件 onPause
  5. started 切换到 created 状态 发送事件 onStop
  6. created 切换到 destroyed 状态 发送事件 onDestroy

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5a7560e59ad64b2e9053631f5562b178~tplv-k3u1fbpfcp-zoom-1.image

框架内定义为枚举类

状态:DESTROYED INITIALIZED CREATED STARTED RESUMED

事件:ON_CREATE ON_START ON_RESUME ON_PAUSE ON_STOP ON_DESTROY

Lifecycle将Activity,Fragment 生命周期的切换抽象为 事件与状态。

事件还可以理解与正常的生命周期一致,

状态怎么回事?是不是少了和onPause,onStop对应的paused,stoped状态?

事件转换为状态的源码如下:

public State getTargetState() {
    switch (this) {
        case ON_CREATE:
        case ON_STOP:
            return State.CREATED;
        case ON_START:
        case ON_PAUSE:
            return State.STARTED;
        case ON_RESUME:
            return State.RESUMED;
        case ON_DESTROY:
            return State.DESTROYED;
        case ON_ANY:
            break;
    }
    throw new IllegalArgumentException(this + " has no target state");
}

通过源码可以看出 状态CREATED 对应 事件ON_CREATEON_STOP。状态STARTED对应事件ON_START,ON_PAUSE。

Lifecycle内部持有当前Activity的状态,如果当前状态为STARTED,那如何确定生命周期处于onStart还是onStop呢?

public class LifecycleRegistry extends Lifecycle {
	//Current state
	private State mState;

}

页面从打开到关闭就是页面的生命周期,对于用户的感受是:不可见—可见—不可见。

从原理图可以明显看出有两个流程:

  1. 不可见 到 可见 ,起个别名:打开流程
  2. 可见 到 不可见 ,起个别名:关闭流程

打开流程的状态更改:INITIALIZEDCREATEDSTARTEDRESUMED

关闭流程的状态更改:RESUMEDSTARTEDCREATEDDESTROYED

状态*CREATED* 在打开流程则表示Activity生命周期处于onCreate

状态*CREATED* 在关闭流程则表示Activity生命周期处于onStop

那么问题来了 如何根据状态 判断处于打开流程 还是 关闭流程呢?

涉及到关于枚举基础知识:

  1. 枚举成员的默认值是0,按照声明顺序+1
  2. 枚举调用****compareTo()****方法进行比较,相等返回0,大于返回正值,小于返回负值

状态枚举值比较

如果Lifecycle中保存的Activity当前状态大于LifecycleObserve的状态,表明是打开流程,页面可见

如果Lifecycle中保存的Activity当前状态小于LifecycleObserve的状态,表明是关闭流程,页面不可见

源码如下:

  1. upFrom 打开流程 状态转换事件
  2. downFrom 关闭流程 状态转换事件
public enum State {

	DESTROYED,

	INITIALIZED,

	CREATED,

	STARTED,

	RESUMED;

}

public static Event upFrom(@NonNull State state) {
            switch (state) {
                case INITIALIZED:
                    return ON_CREATE;
                case CREATED:
                    return ON_START;
                case STARTED:
                    return ON_RESUME;
                default:
                    return null;
            }
        }

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;
            }
        }

虽然我捋清楚状态与事件的关系,但是不能明白为什么要这么设计,整出打开流程,关闭流程。还是太菜了 哈哈哈

4. LiveData简说

感知生命周期的观察者组件。号称关联的Activity销毁时会自动清理,永远不会发生内存泄漏;Activity处于非活跃状态时不会接收任何事件;自动管理生命周期等这些好用的特性都是根据Lifecycle实现的。

比如:

  1. LiveData.observe() 开始就判断 如果Lifecycle的状态等于 DESTROYED 直接return
  2. 创建核心类 LifecycleBoundObserver 并添加到Lifecycle中 观测生命周期
    1. shouldBeActive() 通过Lifecycle判断是否页面是否处于前台
    2. onStateChanged() 判断如果Lifecycle状态为*DESTROYED* 直接移除观察者
  3. LiveData.setValue() 给观察者分发值之前 通过shouldBeActive() 方法检测应用是否处于前台

Lifecycle搞的这么复杂就是为了让三方组件能够感知到生命周期,最典型的例子就是LiveData。

5.Lifecycle工作流程分析

在开始原理分析之前 回顾一下Lifecycle的诞生的意义:作为Activity与开发者之间的抽象层,能够更方便监听生命周期获取Activity状态

它使用大概有两种情况:

  1. 当Activity的生命周期改变,Lifecycle主动通知开发者自定义组件
  2. 当自定义组件有需求时通过Lifecycle获取Activity的状态

Untitled 1.png

如果是我想要实现上述效果必须要解决的问题是:

  1. Activity,Fragment生命周期改变之后 如何通知Lifecycle
  2. 自定义组件获取通过Lifecycle获取Activity,Fragment的状态,这个状态是如何维护的
    1. 官方原理图表明Lifecycle通过内部维护的状态(States)切换发出事件(Event) 这套体系是如何运行的?如何保证一致性?

待着问题,源码分析的流程

  1. 在Activity子类中 通过 getLifecycle() 方法获取 lifecycle,实现类是 LifecycleRegistry 。通过addObserver() 添加的自定义组件也是保存在LifecycleRegistry 内部
  2. ComponentActivityprivate final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); LifecycleRegister声明全局变量,通过构造函数持有Activity引用
  3. 根据的问题猜想,Activity和 LifecycleRegister之前肯定存在某种通信方式。
    1. 可能是LifecycleRegister持有Activity的引用,通过某种手段获取到生命周期的变化
    2. 也可能是LifecycleRegister 公开方法,Activity在生命周期中调用
    3. 其他方式
  4. 通过进入LifecycleRegister源码,持有Activity类型是LifecycleOwner 存储在全局变量mLifecycleOwner
  5. 先验证猜想 ” LifecycleRegister持有Activity的引用,通过某种手段获取到生命周期的变化“
    1. LifecycleRegistry 源码并不复杂只有不到400行,通过全局搜索mLifecycleOwner(Activity) 只有在LifecycleRegistry.addObserver() 和 LifecycleRegistry.sync() 两个方法中用到。并且没有咱们猜想的 通过某种手段获取到Activity的生命周期变化。 所以这个猜想废弃了
  6. 那就可能是第二种猜想 ”LifecycleRegister 公开方法,Activity在生命周期中调用“
    1. ComponentActivity 中搜索LifecycleRegistry 的调用。
    2. 发现只有 getLifecycle() 一处调用,作为方法返回值
    3. 这就难办了 卡住了,
      1. 比较快的方式是 找个别人的源码分析,看看思路
      2. 慢慢的读一哈源码,因为LifecycleRegistry 代码量并不大,按照咱们的猜想肯定是存在一个public方法供外部调用。重要的方法在源码中是留有注释的,能够查看方法作用
      3. 最终找到了handleLifecycleEvent() 作用:设置当前状态,通知自定义组件状态改变
      4. 借助AndroidStudio,查找当前方法都在哪里调用
  7. 发现handleLifecycleEvent() 在两个包下调用:
    1. androidx.fragment.app
    2. androidx.lifecycle
  8. Fragment下的调用和 ComponentActivity 没什么关系,Lifecycle包下的调用都在 ReportFragment 。而ReportFragmentComponentActivity.onCreate() 中调用静态方法。ReportFragment.*injectIfNeededIn*(this);那么我们就看看ReportFragment 是如何实现的
  9. 在Activity调用onCreate时 ReportFragment 添加到Activity中,
    1. 内部重写Fragment生命周期,
    2. 比如:在onStart()调用 dispatch(Lifecycle.Event.ON_START)
    3. dispatch 方法内部调用LifecycleRegistry.handleLifecycleEvent
  10. 到此为止第一个问题得到答案
    1. Activity初始时,添加一个看不见的FragmentReportFragment
    2. 重写ReportFragment 每个生命周期方法,改变时传递事件到LifecycleRegistry
  11. handleLifecycleEvent() 核心方法,承上启下。一方面对接activity,接收生命周期事件。另一方面接收事件后通知自定义组件。
    1. 检查线程
  12. handleLifecycleEvent(Lifecycle.Event) 的核心逻辑如下:
    1. 外部传递的事件(Event) 转化为对应的状态
    2. 调用moveToState() 见名知义,用作切换状态
    3. 如果事件转换的状态 与 内部状态一致 则return
    4. 标记 mHandlingEvent 当前是否正在进行
    5. 如果不一致 则调用 同步方法sync() 进行状态同步,把最新的状态同步给观察者(自定义组件)
    6. sync() 内部 有while 循环语句 while (!isSynced()) 知道所有观察者的状态都一直才会结束循环
  13. 同步过程的关键就是上一章描述的事件与状态的关系
    1. 关闭流程 调用 backwardPass()
    2. 打开流程 调用 forwardPass()
    3. 两个方法内部实现几乎一致,根据所处流程判断状态对应的事件。
      1. 关闭流程中状态 STARTED对应 事件 ON_STOP
      2. 打开流程中状态*STARTED 对应事件* ON_RESUME
      3. 状态转换事件的方法见 Lifecycle.Event.upFrom()Lifecycle.Event.downFrom()
  14. backwardPass()forwardPass() 调用 observer.dispatchEvent() 进行事件分发。最终会调用到LifecycleEventObserver.``onStateChanged()
  15. LifecycleEventObserver 观察者接口 也就是我们的自定义组件,逻辑完成!