【Jetpack】学穿:Lifecycle → 生命周期 (原理篇)(下)

简介: 本质上是围绕着这两个设计模式进行的: 模板模式 → 定义算法骨架,对外开放扩展点,基于 继承 关系实现,子类重写父类抽象方法; 观察者模式 → 对象间定义一对多的依赖,当一个对象状态发生改变,依赖对象都会自动收到通知;

看到这里应该能feel到为什么需要 可重入 的标记了,如果没有的话,可能产生sync()嵌套:


moveToState(state1)
→ sync()
→ moveToState(state1)
  → sync()
addObserver()
→ addObserver()
  → sync()
→ sync()
addObserver()
→ moveToState()
  → sync()
→ sync()


最后都会走 最外层(顶层)的sync(),中间发生的sync() 完全没必要执行,减少不必要的迭代或错误,通过这三个字段配合来完成:mHandlingEventmNewEventOccurredmAddingObserverCounter


然后还有个属性还没弄清楚是干嘛的:


网络异常,图片无法展示
|


解释下:它为了解决 事件嵌套增加新观察者对观察者队列有序性的破坏。怎么说,看代码:


网络异常,图片无法展示
|


假如没有mParentStates,好像还正常,然后注释给了一个反例:


  • Observer1 在 onStart() 回调中把自己从集合中移除,然后添加了新的Observer2;
  • 假如集合中只有Observer1这个观察者,移除后集合就是空的,会导致Observer2直接更新到LifecycleRegister的STARTED状态;
  • 但,此时Observer1的 onStart() 回调还未执行完,而 Observer2 的 ON_START就回调执行完了,显然就违背了LifecycleRegistry的设计 → 观察者的同步是按照顺序执行的


添加了这个属性,在执行观察者回调前 pushParentState() 暂存当前观察者,回调完后 popParentState() 移除观察者,然后执行 calculateTargetState() 时判断是否为空,不为空取出最后一个缓存的观察者,然后取:LifecycleRegister当前状态、

previous当前状态、缓存观察者状态中的最小值,作为当前观察者的状态。


关于 LifecycleRegistry 关键代码的的解析就这些,它还对外暴露了几个改变状态的方法:


网络异常,图片无法展示
|


Activiyt和Fragment中就有用到,等下会碰到,先继续往下走~


② ReportFragment类


一个专门用于分发生命周期事件的无UI界面的Fragment,入口方法 injectIfNeededIn()


网络异常,图片无法展示
|


很清晰明了,API版本大于等于29,直接使用 activity.registerActivityLifecycleCallbacks(),重写生命周期回调方法进行事件分发:


网络异常,图片无法展示
|


API版本小于29,直接开启一个事务,新建一个ReportFragment实例,添加到activity上,在ReportFragment中已对生命周期回调方法进行了重写,完成事件分发:


网络异常,图片无法展示
|


然后 dispatch() 就是调下 LifecycleRegistry.handleLifecycleEvent() 而已。


网络异常,图片无法展示
|


还定义了一个 ActivityInitializationListener 接口:


网络异常,图片无法展示
|


支持外部通过 setProcessListener() 传入自定义实现,在 lifecycle-process 源码中看到过:


网络异常,图片无法展示
|


网络异常,图片无法展示
|


留了个后门,让ProcessLifecycleOwner的onStart()和onResume(),先于第一个Activity执行。


③ ViewTreeLifecycleOwner类


网络异常,图片无法展示
|


看着有点蒙?看下 set() 调用处的代码就知道了:


网络异常,图片无法展示
|


ComponentActivity实现了LifecycleOwner接口,所以这里传入了 根视图 + ComponentActivity这个LifecycleOwner


而在调用 get() 传入view时,通过getParent()一层层往上拿,直到获取到这个LifecycleOwner为止(也可能没有返回空)。


那这有什么用呢?简化代码


View内部需要基于lifecycle进行某些操作时,可以避免Lifecycle的层层传递,比如LiveData订阅。


0x4、Activity中的Lifecycle相关


实现了Lifecycle接口,没干啥活,毕竟生命周期事件分发的活都交给ReportFragment了,直接贴相关代码~


// 定义一个LifecycleRegistry
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ...
    ReportFragment.injectIfNeededIn(this);  // 使用Report分发生命周期事件
    ...
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    Lifecycle lifecycle = getLifecycle();
    if (lifecycle instanceof LifecycleRegistry) {
        // 设置mLifecycleRegistry当前状态为CREATED
        ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
    }
    ...
}
@Override
public Lifecycle getLifecycle() {
    return mLifecycleRegistry;
}


0x5、Fragment中的Lifecycle相关


同样实现了LifecycleOwner接口,实例化了一个LifecycleRegistry用于生命周期事件转发。


有一点要注意,在大多数情况下Fragment与其管理的View(视图)的生命周期是一致的,但存在特例:


Fragment被replace()时 → FragmentTransaction.detach() → 回调onDestroyView()销毁视图 → 不走onDestory() → 使得Fragment状态得以保留,当前内存空间得以释放,下次加载直接onCreateView(),速度更快。


这样的操作也导致了Fragment的生命周期比View长,所以Fragment还定义了一个 FragmentViewLifecycleOwner 来单独处理View的生命周期,官方文档有给出 《Fragment lifecycle》 给出了这样一张图:


网络异常,图片无法展示
|


源码注释中也有给出Fragment中管理的View:生命周期与Fragment自身回调间的对应关系


网络异常,图片无法展示
|


直接抠出来,方便看:


  • onViewStateRestored()后ON_CREATE
  • onStart()后ON_START
  • onResume()后ON_RESUME
  • onPause()前ON_PAUSE
  • onStop()前ON_STOP
  • onDestroyView()前ON_DESTROY


可调用 getViewLifecycleOwner() 获得View的LifecycleOwner哈~


网络异常,图片无法展示
|


Fragment中涉及到状态流转的核心代码如下:


void performCreate(Bundle savedInstanceState) {
    if (Build.VERSION.SDK_INT >= 19) {
        mLifecycleRegistry.addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_STOP) {
                    if (mView != null) {
                        mView.cancelPendingInputEvents();
                    }
                }
            }
        });
    }
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
void performStart() {
    mState = STARTED;
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }
}
void performResume() {
    mState = RESUMED;
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }
}
void performPause() {
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
    }
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
    mState = AWAITING_ENTER_EFFECTS;
}
void performStop() {
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
    }
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
    mState = ACTIVITY_CREATED;
}
void performDestroy() {
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
    mState = ATTACHED;
}


既有Fragment Lifecycle的State,又有ViewLifecycleOwner的State,还有Fragment自身的State,这个要区分哈:


网络异常,图片无法展示
|


另外,相比以前的源码,Fragment发生了较大的改动,比如状态管理相关的剥离到 FragmentStateManager 中了,笔者目前还不太了解,就不先不往下挖了,后续专门研究Fragment再说吧~


0x6、小结


关于源码的解析暂且到这里吧,Lifecycle的路数基本摸清了,小结下要点方便回顾:


  • ① Lifecycle的核心思想是:模板模式 + 观察者模式
  • Lifecycle抽象类抽象被观察者,定义了两个生命周期相关的枚举 EventState,统一了State升降级对应触发的Event(关联关系),提供了添加、移除观察者,获取当前State的三个抽象方法;
  • LifecycleObserver:空接口,类型标记,抽象观察者
  • FullLifecycleObserverLifecycleEventObserver:继承LifecycleObserver接口,提供两种不同的回调方式;
  • DefaultLifecycleObserver:继承FullLifecycleObserver,利用Java 8特性【接口声明默认方法】,默认重写了回调方法,具体观察者
  • LifecycleOwner:提供一个获取Lifecycle的方法;
  • Lifecycling → 对传入LifecycleOwner进行统一的类型包装,使得Event分发过程得以统一入口;
  • LifecycleRegistry具体观察者,组件状态维护,使用自定义支持迭代时增删元素的 FastSafeIterableMap (HashMap套链表) 保存观察者。键为LifecycleObserver,值为 ObserverWithState,其中包含观察者与状态关联,并提供事件分发方法dispatchEvent();
  • ⑨ 通过三个变量:mHandlingEventmNewEventOccurredmAddingObserverCounter 的配合来解决 事件嵌套 引起的sync()多次执行;
  • ⑩ 额外定义了一个 mParentStates 来解决 事件嵌套增加新观察者对观察者队列有序性的破坏


以上就是本节的全部内容,后续肝多几个组件,再来个实战篇吧,谢谢~


Tips:关于Lifecycle库的改动可以参见:Lifecycle,其他库亦是如此~


参考文献:



相关文章
|
Java API Android开发
Jetpack 之 LifeCycle 组件原理解析
1. LifeCycle 是如何监听到 Activity/Fragment 生命周期变化的? 2. LifeCycle 如何将生命周期变化的事件分发给观察者的?
129 0
Jetpack 之 LifeCycle 组件原理解析
|
Java API 开发工具
Jetpack 之 LifeCycle 组件使用详解
LifeCycle 是一个可以感知宿主生命周期变化的组件。常见的宿主包括 Activity/Fragment、Service 和 Application。LifeCycle 会持有宿主的生命周期状态的信息,当宿主生命周期发生变化时,会通知监听宿主的观察者。
124 0
Jetpack 之 LifeCycle 组件使用详解
|
安全 Android开发
Android Jetpack系列之Lifecycle
`Lifecycle`可以让某一个类变成`Activity`、`Fragment`的生命周期观察者类,监听其生命周期的变化并可以做出响应。`Lifecycle`使得代码更有条理性、精简、易于维护。
107 0
|
7月前
|
存储 安全 Android开发
构建高效的Android应用:Kotlin与Jetpack的结合
【5月更文挑战第31天】 在移动开发的世界中,Android 平台因其开放性和广泛的用户基础而备受开发者青睐。随着技术的进步和用户需求的不断升级,开发一个高效、流畅且易于维护的 Android 应用变得愈发重要。本文将探讨如何通过结合现代编程语言 Kotlin 和 Android Jetpack 组件来提升 Android 应用的性能和可维护性。我们将深入分析 Kotlin 语言的优势,探索 Jetpack 组件的核心功能,并通过实例演示如何在实际项目中应用这些技术。
|
6月前
|
数据管理 API 数据库
探索Android Jetpack:现代安卓开发的利器
Android Jetpack是谷歌为简化和优化安卓应用开发而推出的一套高级组件库。本文深入探讨了Jetpack的主要构成及其在应用开发中的实际运用,展示了如何通过使用这些工具来提升开发效率和应用性能。
|
5月前
|
存储 数据库 Android开发
🔥Android Jetpack全解析!拥抱Google官方库,让你的开发之旅更加顺畅无阻!🚀
【7月更文挑战第28天】在Android开发中追求高效稳定的路径?Android Jetpack作为Google官方库集合,是你的理想选择。它包含多个独立又协同工作的库,覆盖UI到安全性等多个领域,旨在减少样板代码,提高开发效率与应用质量。Jetpack核心组件如LiveData、ViewModel、Room等简化了数据绑定、状态保存及数据库操作。引入Jetpack只需在`build.gradle`中添加依赖。例如,使用Room进行数据库操作变得异常简单,从定义实体到实现CRUD操作,一切尽在掌握之中。拥抱Jetpack,提升开发效率,构建高质量应用!
71 4
|
6月前
|
Android开发
Jetpack Compose: Hello Android
Jetpack Compose: Hello Android
|
7月前
|
Java 数据库 Android开发
构建高效Android应用:Kotlin与Jetpack的完美结合
【5月更文挑战第28天】 在现代移动开发领域,Android平台以其广泛的用户基础和开放性受到开发者青睐。随着技术的不断进步,Kotlin语言以其简洁性和功能性成为Android开发的首选。而Android Jetpack组件则为开发者提供了一套高质量的设计架构、工具和UI组件,以简化应用程序的开发过程。本文将探讨如何利用Kotlin语言和Android Jetpack组件共同构建一个高效的Android应用程序,涵盖从语言特性到架构模式的全面分析,并提供具体的实践指导。
|
7月前
|
安全 数据库 Android开发
构建高效Android应用:采用Kotlin与Jetpack的实践指南
【5月更文挑战第22天】 在移动开发领域,Android系统因其开放性和广泛的用户基础而备受开发者青睐。随着技术的不断演进,Kotlin语言以其简洁性和功能性成为Android开发的首选语言。本文将深入探讨如何结合Kotlin和Android Jetpack组件来构建一个高效且易于维护的Android应用。我们将重点讨论如何使用Jetpack的核心组件,如LiveData、ViewModel和Room,以及Kotlin的语言特性来优化代码结构,提高应用性能,并简化数据管理。通过具体案例分析,本文旨在为开发者提供一套实用的技术指导,帮助他们在竞争激烈的市场中脱颖而出。