本文正在参与「金石计划 . 瓜分6万现金大奖」

Hi , 你好 :)

导言

在2022的今天,AndroidX 遍及的情况下,JetPack Lifecycle 也早现已成为了开发中的根底设施,小到 View(扩展库) ,大到 Activity,都隐藏着它的身影,而了解 Lifecycle 也正是理解 JetPack 组件系列库生命感知规划的根底。

本篇定位中级,将从布景到源码完成,然后理解其背后的规划思想。

导航

看完本篇,你将会搞清以下问题:

  • Lifecycle 的前世此生;
  • Lifecycle 能够干什么;
  • Lifecycle 源码解析;

布景

在开端前,咱们先聊聊关于 Lifecycle 的前世此生,然后便于咱们更好的理解 Lifecycle 存在的含义。

洪荒之时

Lifecycle 之前(不排除现在),假如咱们要在某个生命周期去履行一些操作时,常常会在Act或许Fragment写许多模版代码,如下两个示例:

  1. 比方,有一个定时器,咱们需求在 Activity 封闭时将其封闭,然后防止因而导致的内存问题,所以咱们自然会在 onDestory() 中去stop一下。这些事看起来似乎不费事,但假如是一个重复多处运用的代码,细心的开发者会将其独自抽离成为一个 case ,然后经过组合的办法降低咱们主类中的逻辑,但不可防止咱们仍然还要存在很多模版代码,由于每次都需求 onStop() 整理或许其他操作(除非写到base,但不可接受☹️)。

假如能不需求开发者自己手动,该有多好?

  1. 在老版别的友盟中,咱们常常甚至需求在基类的 Activity 中复写 onResume()onPause() 等办法,这些工作说费事也不费事,但总是感觉很不舒畅。不过,有经历的开发者必定会想喷,为什么一个三方库,你就自己不会经过application.registerActivityLifecycleCallbacks 监听吗。

留意,Application有监听大局Act生命周期的办法,Act也有这个办法。

盘古开天

JetPack 之前,Android 一向秉承着传统的 MVC 架构,即 xml 作为 View, Activity 作为 ControlModel 层由数据模型或许仓库而定。虽然说官方曾经有一个MVP的示例,但真正用的人并不多。再加上官方一向也没推荐过 Android 的架构攻略,这就导致传统的Android开发办法和系统的碎片化相同☹️,五花八门。跟着时间的推移,眼看前端的MVVM已更加老练,后有Flutter,再加上开发者的需求等布景下,Google于2017年发布了新的开发架构: AAC,全名 Architecture,而且伴跟着一系列相关组件,然后协助开发者提高开发体验,降低错误概率,削减模版代码。

而本篇的主题 Lifecycle 正是其间作为根底设施的存在,在 sdk26 之后,更是被写入了根底库中。

那Lifecycle到底是干什么的呢?

Lifecycle 做的工作很简单,其便是用于检测组件(FragmentAct) 的生命周期,然后不必强依赖于 ActivityFragment ,协助开发者降低模版代码。

常见用法

在官网中,关于 Lifecycle 的生命周期感知的整个流程如下所示:

由浅入深,详解 Lifecycle 生命周期组件的那些事


Api介绍

相关字段

  • Event

    生命周期事情,对应详细的生命周期:

    ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY

  • State

    生命周期状况节点,与 Event 紧密相关,Event 是这些结点的详细边界,换句话说,State 代表了这一时间的详细状况,其相当于一个规模集,在这个规模里,都是这个状况。而Event代表这一状况集里边触发的详细事情是什么。

    INITIALIZED

    结构函数初始化时,且未收到 `onCreate()` 事情时的状况;
    

    CREATED

    在 `onCreate()` 调用之后,`onStop()` 调用之前的状况;
    

    STARTED

    在 `onStart()` 调用之后,`onPause()` 调用之前的状况;
    

RESUMED

    在 `onResume()` 调用时的状况;
   `DESTROYED`
   `onDestory()` 调用时的状况;

相关接口

  • LifecycleObserver

    根底 Lifecycler 完成接口,一般调用不到,可用于自定义的组件,然后防止在 Act 或许 Fragment 中的模版代码,例如ViewTreeLifecyleOwner

  • LifecycleEventObserver

    能够接受所有生命周期改变的接口;

  • FullLifecycleObserver

    用于监听生命周期改变的接口,提供了 onCreate()onStart()onPause()onStop()onDestory()onAny();

  • DefaultLifecycleObserver

    FullLifecycleObserver 的默许完成版别,比较前者,增加了默许 null 完成;


举个栗子

如下所示,经过完成 DefaultLifecycleObserver 接口,咱们能够在中重写咱们想要监听的生命周期办法,然后将业务代码从主类中拆离出来,且更便于复用。最终在相关类中直接运用 lifecycle.addObserver() 办法增加实例即可,这也是google推荐的用法。

由浅入深,详解 Lifecycle 生命周期组件的那些事

上述示例中,咱们运用了 viewLifecycle ,而不是 lifecycle ,这儿顺便提一下。

见名之意,前者是视图(view)生命周期,后者则对错视图的生命周期,详细差异如下:

viewLifecycle 只会在 onCreateView-onDestroyView 之间有效。

lifecycle 则是代表 Fragment 的生命周期,在视图未创立时,onCreate(),onDestory() 时也会被调用到。


或许你有某个自定义View,想感知Fragment或许Act的生命周期,然后做一些工作,比方Banner组件等,与上面示例类似:

由浅入深,详解 Lifecycle 生命周期组件的那些事

当然你也能够选择依赖:androidx.lifecycle:lifecycle-runtime 扩展库。

然后运用 view.findViewTreeLifecycleOwner() 的扩展函数取得一个 LifecycleOwner,然后在View内部自行监听生命周期,革除在Activity手动增加观察者的模版代码。

lifecycle.addObserver(view)

源码解析

Lifecycle

在官方的解说里,Lifecycle 是一个类,用于存储有关组件(Act或Fragment)声明周期状况新的类,并答应其他目标观察此类。

直接去看 Lifecycle 的源码,其完成办法如下:

由浅入深,详解 Lifecycle 生命周期组件的那些事
总体规划如上所示,比较简单,便是观察者模式的接口模版:

运用者完成 LifecycleObserver 接口(),然后调用 addObserver() 增加到观察者列表,撤销观察者时调用 rmeoveObserver() 移除掉即可。在相应的生命周期变化时,遍历观察者列表,然后告诉完成了 LifecycleObserver 的实例,然后调用相应的办法。

由于其是一个抽象类,所以咱们调用的一般都是它的详细完成类,也便是 LifecycleRegistry ,目前也是其的唯一完成类。


LifecycleRegistry

Lifecycle 的详细完成者,正如其名所示,首要用于办理当时订阅的 观察者目标 ,所以也承担了 Lifecycle 详细的完成逻辑。由于源码较长,所以咱们做了一些删减,只需重视主流程即可,伪代码如下:

public class LifecycleRegistry extends Lifecycle {
    // 生命周期观察者map,LifecycleObserver是观察者接口,ObserverWithState详细的状况分发的包装类
  private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap;
    // 当时生命周期状况
  private State mState = INITIALIZED;
    // 持有生命周期的提供商,Activity或许Fragment的弱引用
  private final WeakReference<LifecycleOwner> mLifecycleOwner;
    // 当时正在增加的观察者数量,默许为0,超越0则以为多线程调用
  private int mAddingObserverCounter = 0;
    // 是否正在分发事情
  private boolean mHandlingEvent = false;
    // 是否有新的事情产生
  private boolean mNewEventOccurred = false;
    // 存储主类的事情state
  private ArrayList<State> mParentStates = new ArrayList<>();
​
  @Override
  public void addObserver(@NonNull LifecycleObserver observer) {
    // 初始化状况,destory or init
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
      //  初始化实际分发状况的包装类
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
      // 将观察者增加到详细的map中,假如现已存在了则回来之前的,不然创立新的增加到map中
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        // 假如上一步增加成功了,putIfAbsent会回来null
    if (previous != null) {
      return;
     }
      // 假如act或许ff被回收了,直接return
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
      return;
     }
        // 当时增加的观察者数量!=0||正在处理事情
    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
      //  取得观察者当时的状况
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
      //  假如当时观察者状况小于当时生命周期所在状况&&这个观察者现已被存到了观察者列表中
    while ((statefulObserver.mState.compareTo(targetState) < 0
        && mObserverMap.contains(observer))) {
        // 保存当时的生命周期状况
      pushParentState(statefulObserver.mState);
        // 回来当时生命周期状况对应的接下来的事情序列
      final Event event = Event.upFrom(statefulObserver.mState);
       ...
      // 分发事情
      statefulObserver.dispatchEvent(lifecycleOwner, event);
        // 移除当时的生命周期状况
      popParentState();
      // 再次取得当时的状况,以便继续履行
      targetState = calculateTargetState(observer);
     }
      // 处理一遍事情,保证事情同步
    if (!isReentrance) {
      sync();
     }
      // 回归默许值
    mAddingObserverCounter--;
   }
    ...
  static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;
​
    ObserverWithState(LifecycleObserver observer, State initialState) {
        // 初始化事情观察者
      mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
      mState = initialState;
     }
​
    void dispatchEvent(LifecycleOwner owner, Event event) {
      State newState = event.getTargetState();
      mState = min(mState, newState);
      mLifecycleObserver.onStateChanged(owner, event);
      mState = newState;
     }
   }
    ...
}

咱们要点重视的是 addObserver() 即订阅生命周期改变时的逻辑,详细如下:

  1. 先初始化当时观察者的状况,默许两种,即 DESTROYED(销毁) 或许 INITIALIZED(无效),别离对应 onDestory()onCreate() 之前;
  2. 初始化 状况观察者(ObserverWithState) ,内部运用 Lifecycling.lifecycleEventObserver() 将咱们传递进来的 生命周期观察者(LifecycleObser) 包装为一个 生命周期[事情]观察者LifecycleEventObserver,然后在状况改变时触发事情告诉;
  3. 将第二步生成的状况观察者增加到缓存map中,假如之前现已存在,则停止接下来的操作,不然继续初始化;
  4. 调用 calculateTargetState() 取得当时真正的状况。
  5. 开端事情轮训,假如 当时观察者的状况小于此刻真正的状况 && 观察者现已被增加到了缓存列表 中,则取得当时观察者下一个状况,并触发相应的事情告诉 dispatchEvent(),然后继续轮训。直到不满足判别条件;

需求留意的是, 关于状况的判别,这儿运用了compareTo() ,然后判别当时状况枚举是否小于指定状况。


Activity中的完成

Tips:

写过权限检测库的小伙伴,应该很熟悉,为了防止在 Activity 中手动完成 onActivityRequest() ,然后完成以回调的办法取得权限成果,咱们往往会运用一个通明的 Fragment ,然后将模版办法拆离到独自类中,而这种完成办法正是组合的思想。

LifecycleActivity 中的完成正是上述的办法。


如下所示,当咱们在 Activity 中调用 lifecycle 目标时,内部实际上是调用了 ComponentActivity.mLifecycleRegistry,详细逻辑如下:

由浅入深,详解 Lifecycle 生命周期组件的那些事
不难发现,在咱们的 Activity 初始化时,相应的 LifecycleRegistry 现已被初始化。

在上面咱们说过,为了防止对基类的入侵,咱们一般会用组合的办法,所以这儿的 ReportFragment 正是 LifecycleActivity 中详细的逻辑承载方,详细逻辑如下:

ReportFragment.injectIfNeededIn

由浅入深,详解 Lifecycle 生命周期组件的那些事

内部会对sdk进行判别,对应着两套流程,关于 sdk>=29 的,经过注册 Activity.registerActivityLifecycleCallbacks() 事情完成监听,关于 sdk<29 的,重写 Fragment 相应的生命周期办法完成。

ReportFragment 详细逻辑如下:

由浅入深,详解 Lifecycle 生命周期组件的那些事


Fragment中的完成

直接去 Fragment.lifecycle 中看一下即可,伪代码如下:

由浅入深,详解 Lifecycle 生命周期组件的那些事

总结如下:lifecycle 实例会在 Fragment 结构函数 中进行初始化,而 mViewLifecycleOwner 会在 performCreateView() 履行时初始化,然后在相应的 performXxx 生命周期履行时,调用相应的 lifecycle.handleLifecycleEvent() 然后完成事情的告诉。

总结

Lifecycle 作为 JetPack 的基石,而理解其是咱们贯穿相应生命周期的关键所在。

关于生命周期的告诉,Lifecycle 并没有选用直接告诉的办法,而是选用了 Event(事情) + State(状况) 的规划办法。

  • 关于外部生命周期订阅者而言,只需求重视事情 Event 的调用;
  • 而关于Lifecycle而言,其内部只重视 State ,并将生命周期区分为了多个阶段,每个状况又代表了一个事情集,然后关于外部调用者而言,无需拘泥于当时详细的状况是什么。

在详细的完成底层上面:

  • Activity 中,选用组合的办法而非继承,在 Activity.onCreate() 触发时,初始化了一个通明Fragment,然后将逻辑存于其间。关于sdk>=29的版别,由于 Activity 自身有监听生命周期的办法,然后直接注册监听器,并在相应的会调用触发生命周期事情更新;关于sdk<29的版别,由于需求兼容旧版别,所以重写了 Fragment 相应的生命周期办法,然后完成手动触发更新咱们的生命周期观察者。
  • Fragment 中,会在 Fragment 结构函数中初始化相应的 Lifecycle ,并重写相应的生命周期办法,然后触发事情告诉,完成生命周期观察者的更新。

每逢咱们调用 addObserver() 增加新的观察者时:

内部都会对咱们的观察者进行包装,并将其包装为一个详细的事情观察者 LifecycleEventObserver,以及生成当时的观察者对应的状况实例(内部持有LifecycleEventObserver),并将其保存到 缓存map 中。接着会去比照当时的 观察者的状况lifecycle此刻实际状况 ,假如 当时观察者状况<lifecycle对应的状况 ,则触发相应 Event 的告诉,并 更新此观察者对应的状况 ,不断轮训,直到当时观察者状况 >= lifecycle 对应状况。

参阅

  • Android-运用生命周期感知型组件处理生命周期

关于我

我是 Petterp ,一个 Android工程师 ,假如本文对你有所协助,欢迎点赞支撑,你的支撑是我继续创作的最大鼓舞!