zoukankan      html  css  js  c++  java
  • Lifecycle详细分析

    Lifecycle源码分析

    目录介绍

    • 01.Lifecycle的作用是什么
    • 02.Lifecycle的简单使用
    • 03.Lifecycle的使用场景
    • 04.如何实现生命周期感知
    • 05.注解方法如何被调用
    • 06.addObserver调用分析
    • 07.知识点梳理和总结一下

    00.使用AAC实现bus事件总线

    • 利用LiveData实现事件总线,替代EventBus。充分利用了生命周期感知功能,可以在activities, fragments, 或者 services生命周期是活跃状态时更新这些组件。支持发送普通事件,也可以发送粘性事件;还可以发送延迟消息,以及轮训延迟消息等等。
    • https://github.com/yangchong211/YCLiveDataBus

    01.Lifecycle的作用是什么

    • Lifecycle 是一个专门用来处理生命周期的库,它能够帮助我们将 Activity、Fragment 的生命周期处理与业务逻辑处理进行完全解耦,让我们能够更加专注于业务;通过解耦让 Activity、Fragment 的代码更加可读可维护。

    02.Lifecycle的简单使用

    • 直接看一下下面的案例,用法十分简单,代码如下
      • 可以通过 getLifecycle() 方法拿到 Lifecycle, 并添加 Observer 来实现对 Activity 生命周期的监听。
    • 然后打印日志记录如下所示
      • 可以发现Lifecycle是可以监听activity的生命周期的。
      • 在activity创建的时候,activity中生命周期onCreate方法优先LifecycleObserver中onCreate方法先执行;关闭的时候相反!

    03.Lifecycle的使用场景

    • Lifecycle 的应用场景非常广泛,我们可以利用 Lifecycle 的机制来帮助我们将一切跟生命周期有关的业务逻辑全都剥离出去,进行完全解耦。
      • 比如视频的暂停与播放,
      • Handler 的消息移除,
      • 网络请求的取消操作,
      • Presenter 的 attach&detach View
      • 暂停和恢复动画绘制
      • 并且可以以一个更加优雅的方式实现,还我们一个更加干净可读的 Activity & Fragment。
    • 关于网络请求的取消操作
    • 停止和开启视频缓冲
      • 使用支持生命周期的组件尽快开始视频缓冲,但是将播放推迟到应用程序完全启动。 还可以使用可识别生命周期的组件在应用程序销毁时终止缓冲。
    • 启动和停止网络连接
      • 使用可感知生命周期的组件可以在应用程序处于前台状态时实时更新(流式传输)网络数据,并在应用程序进入后台时自动暂停。
    • 暂停和恢复动画绘制
      • 当应用程序在后台运行时,使用生命周期感知组件处理暂停动画绘制,并在应用程序在前台运行后恢复绘制。

    04.如何实现生命周期感知

    • 看到上面的简单案例,可以发现使用了注解@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)标注的方法,既可以执行生命周期的监听。
    • 那么追踪到Lifecycle.Event类,看看还有哪里使用到了该注解,截图如下所示,这里我们就先看一下ReportFragment类,看上去应该跟Fragment有关系!
      • image

    4.1 生命周期事件与状态

    • 上面案例中使用到了注解,那么它究竟有那些状态呢?
      • Lifecycle是一个抽象类,里面主要有两个功能,一个是Event生命周期,一个是State状态。
      • Lifecycle.Event表示生命周期的状态,与 Activity 生命周期类似。
      • Lifecycle.State表示当前组件的生命周期状态,
    • Event 与 State 的关系(摘自网络)
      • image

    4.2 ReportFragment类分析

    • 源码如下所示,这里只是摘取了部分和生命周期有关的源代码。
      • 重写了生命周期回调的方法,可以看到生命周期方法中调用了dispatch(Lifecycle.Event.XXX),是这个 ReportFragment 在发挥作用。
      • Lifecycle 利用了 Fragment 来实现监听生命周期,并在最终利用 dispatch 的方法来分发生命周期事件。
      • 在Fragment生命周期发生变化时调用dispatch方法来分发生命周期,在里面调用了LifecycleRegistry的handleLifecycleEvent方法。
    • 然后再来看一下哪里用到了这个ReportFragment类,具体追踪到LifecycleDispatcher中的DispatcherActivityCallback内部类中的onActivityCreated方法,源码如下所示
    • 接着看一下handleLifecycleEvent(event)源码代码,可以发现根据Event状态来获取State状态,然后分发状态。后续还会分析到……

    4.3 ComponentActivity类分析

    • fragment需要依赖宿主activity。通过搜索ReportFragment.injectIfNeededIn调用地方,发现 ComponentActivity 调用了该方法。(API 28 以下的版本是 SupportActivity )
      • 内部创建了一个 LifecycleRegistry 成员对象,并且该ComponentActivity类实现了 LifecycleOwner 。
      • 在 onCreate 方法里 调用了 ReportFragment.injectIfNeededIn(this); 注入了 ReportFragment。通过getLifecycle可以获取mLifecycleRegistry对象!
      • Lifecycle是一个抽象类,LifecycleRegistry是它的实现子类,主要是管理Observer,

    05.注解方法如何被调用

    • OnLifecycleEvent 注解:
      • 看到有 RetentionPolicy.RUNTIME 修饰,表示运行时注解,在运行时通过反射去识别的注解。
      • 运行时注解一般和反射机制配合使用,相比编译时注解性能比较低,但灵活性好,实现起来比较简单。
    • 之前在了解完生命周期监听的原理的同时,我们也看到了生命周期事件的接收者 LifecycleRegistry ,是它的 handleLifecycleEvent() 接收了事件,我们继续追踪。
    • 其实从方法注释就能看出来了,就是它处理了状态并通知了 observer 。看下 getStateAfter() 方法:
      • getStateAfter() 这个方法根据当前 Event 获取对应的 State ,细看其实就是 【2.3.3】中那个图的代码实现。
    • 接下去看 sync() 方法:
    • sync 方法里对比了当前 mState 以及上一个 State ,看是应该前移还是后退,这个对应了生命周期的前进跟后退,打个比方就是从 onResume -> onPause (forwardPass),onPause -> onResume (backwardPass),拿 backwardPass() 举例吧。(forwardPass方法处理类似)
    • 通过源码可以看到, backwardPass() 方法调用 downEvent 获取往回退的目标 Event。可能比较抽象,举个例子,在 onResume 的状态,我们按了 home,这个时候就是 RESUMED 的状态变到 STARTED 的状态,对应的要发送的 Event 是 ON_PAUSE,这个就是 backwardPass() 的逻辑了。如果前面的代码都是引子的话,最终看到了一丝分发的痕迹了—— observer.dispatchEvent(lifecycleOwner, event)。
    • 可以看到最后调用了 GenericLifecycleObserver.onStateChanged() 方法,再跟。
      • 这个类的代码比较多,不过也不复杂。可以看到最后代码走到了invokeCallback() ,通过反射调用了方法。
      • 而这个方法是 createInfo() 方法中反射遍历我们注册的 Observer 的方法找到的被 OnLifecycleEvent 注解修饰的方法,并且按 Event 类型存储到了 info.mEventToHandlers 里。
      • 在 Observer 用注解修饰的方法,会被通过反射的方式获取,并保存下来,然后在生命周期发生改变的时候再找到对应 Event 的方法,通过反射来调用方法。

    06.addObserver调用分析

    • 看一下Lifecycle中addObserver方法,发现它是一个抽象方法,那么就去找它的实现类,这里先来看一下LifecycleRegistry类中的addObserver方法实现代码
    • 然后看一下ObserverWithState类,追溯代码到Lifecycling.getCallback(observer),看看里面做了什么
    • 接着来看看Lifecycling类中getCallback方法
      • 判断该Observer是否是GenericLifecycleObserver,是的话返回本身;如果是FullLifecycleObserver,则直接创建一个FullLifecycleObserverAdapter对象
      • 判断是否包含注解处理器 查找是否包含“类名__LifecycleAdapter”的类 包含并且有OnLifecycleEvent注解则返回SingleGeneratedAdapterObserver/CompositeGeneratedAdaptersObserver
      • 如果以上提交都不满足就通过反射调用回调方法
    • 然后查看一下SingleGeneratedAdapterObserver类
      • 通过ObserverWithState#dispatchEvent方法最后调用的实际是SingleGeneratedAdapterObserver里面的onStateChanged方法
      • 在SingleGeneratedAdapterObserver里面调用了Adapter的callMethods方法
      • 这个是
    • 然后看一下CompositeGeneratedAdaptersObserver类
      • 通过ObserverWithState#dispatchEvent方法最后调用的实际是CompositeGeneratedAdaptersObserver里面的onStateChanged方法
      • 在CompositeGeneratedAdaptersObserver里面遍历mGeneratedAdapters,然后也是调用callMethods方法
    • 最后看一下ReflectiveGenericLifecycleObserver类的代码
      • 反射调用回调函数,不过这里听过class对象,从ClassesInfoCache获取info信息。先从map里拿,拿不到通过createInfo函数扫描类里面的方法。具体分析可以看源码……
    • 当addObserver的时候最后实际传入的是一个包装好的ObserverWithState对象 然后调用onStateChanged方法来分发状态。使用处理器来提高性能,避免反射造成的性能消耗。

    07.知识点梳理和总结一下

    • Lifecycle 库通过在 SupportActivity 的 onCreate 中注入 ReportFragment 来感知发生命周期;
    • Lifecycle 抽象类,是 Lifecycle 库的核心类之一,它是对生命周期的抽象,定义了生命周期事件以及状态,通过它我们可以获取当前的生命周期状态,同时它也奠定了观察者模式的基调;(我是党员你看出来了吗:-D)
    • LifecycleOwner ,描述了一个拥有生命周期的组件,可以自己定义,不过通常我们不需要,直接使用 AppCompatActivity 等即可;
    • LifecycleRegistry 是Lifecycle的实现类,它负责接管生命周期事件,同时也负责Observer` 的注册以及通知;
    • ObserverWithState ,是 Observer 的一个封装类,是它最终 通过 ReflectiveGenericLifecycleObserve 调用了我们用注解修饰的方法;
    • LifecycleObserver ,Lifecycle 的观察者,利用它我们可以享受 Lifecycle 带来的能力;
    • ReflectiveGenericLifecycleObserver,它存储了我们在 Observer 里注解的方法,并在生命周期发生改变的时候最终通过反射的方式调用对应的方法。

    参考博客

    开源LiveData事件总线:https://github.com/yangchong211/YCLiveDataBus

  • 相关阅读:
    [leetcode-102-Binary Tree Level Order Traversal]
    c# 常规验证基类
    不错的silverlight教程
    js 遮罩层请稍后
    登陆冻结账户思路
    mvc json 日期问题的最简单解决方法
    EF 常见语句以及sql语句简单 后续继续添加
    Entity Framework edmx(mapping文件)
    asp.net服务器推送长连接
    数据字典根据组别再分类
  • 原文地址:https://www.cnblogs.com/yc211/p/12447068.html
Copyright © 2011-2022 走看看