关于Lifecycle,来讲个明白

lifecycle是什么?我将通过这篇文章,梳理并讲解清楚。在 Android 中,通常所说的生命周期 (lifecycle) 指的是一个 Activity、Fragment 或其他应用组件从创建到销毁的整个过程。这不是我们这篇讲解的点。

这里主要讲解:androidx.lifecycle ,是一个 Android Jetpack 组件,它是现代 Android 架构中处理生命周期的官方解决方案 。它不仅仅指 Activity 或 Fragment 的生命周期回调,而是提供了一套完整的工具和接口,让开发者能够构建生命周期感知型组件

为什么要使用 androidx.lifecycle?

  • 解耦 : 它将业务逻辑和视图逻辑彻底解耦。你不再需要在 Activity/Fragment 中手动处理大量的生命周期回调。LifecycleObserver 可以在外部处理,让你的 Activity 变得更简洁。
  • 避免内存泄漏 : LiveData 只有在观察者活跃时才发送更新,当观察者被销毁时,它会自动移除绑定。这从根本上避免了因观察者未解绑而导致的内存泄漏。
  • 跨越配置更改 : 配合 ViewModel,可以轻松地在屏幕旋转等配置更改后恢复数据,极大地提升了用户体验。

总结来说,androidx.lifecycle 不仅仅是"一个生命周期",而是一个强大的工具集。它将生命周期管理提升到了一个新的层次,让开发者能够编写出更健壮、更易维护、更解耦的 Android 应用。

大体上分为下面这些:

1、Lifecycle

Lifecycle 是一个抽象类,这是重点 ,它负责存储生命周期的状态和事件 。每个 LifecycleOwner 都会有一个 Lifecycle 对象。

  • Lifecycle.State : 枚举了组件的当前状态,例如 INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED。
  • Lifecycle.Event : 枚举了从一个状态转换到另一个状态的事件,例如 ON_CREATE, ON_RESUME, ON_PAUSE, ON_DESTROY

2、LifecycleOwner

LifecycleOwner 是一个接口,这是重点 。任何实现它的类都可以拥有一个生命周期对象 (Lifecycle) ,就是接口里已经包含了Lifecycle这个抽象类。它是整个生命周期感知的核心,所有感知都是基于这个接口。

ComponentActivity 和 Fragment 都已经默认实现了这个接口,所以它们可以作为生命周期的宿主,现在mvi/mvvm模式下,都是使用这个:

  • 在activity里一般直接使用this就可以了。
  • fragment一般使用this.viewLifecycleOwner,后面会说明为什么
ViewModel

ViewModel 也是一个核心组件。它与 LifecycleOwner 关联,但其生命周期跨越了配置更改 。ViewModel 本身不实现 LifecycleOwner,但它经常与 LiveData或StateFlow 配合使用,来响应宿主的生命周期变化。

3、LifecycleObserver

LifecycleObserver 是一个标记接口,它代表一个生命周期感知型组件 。实现了这个接口的类可以在宿主(如 Activity)的生命周期状态发生变化时,自动接收到通知。

  • 实现方式 : 你可以在 LifecycleObserver 的方法上使用 @OnLifecycleEvent 注解,来指定在哪个生命周期事件发生时执行特定的代码
Kotlin 复制代码
class MyObserver : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun connectListener() {
        // 在宿主 Activity 的 onResume() 时执行
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun disconnectListener() {
        // 在宿主 Activity 的 onPause() 时执行
    }
}

4、ViewTreeLifecycleOwner

在 androidx.lifecycle 出现之前,我们通常只能通过 Activity 或 Fragment 来获取生命周期对象。但在一些复杂场景下,比如自定义 View 或 RecyclerView 中的列表项,我们希望这些视图也能感知生命周期,以便在适当的时机执行或停止某些操作。

ViewTreeLifecycleOwner 的出现正是为了解决这个问题。它是一个 Jetpack 库 中的工具类,通过它,你可以将一个 LifecycleOwner(比如 Activity 或 Fragment)绑定到整个视图层次结构中。这样我们自己在实现LifecycleObserver,就可以感知生命周期。

核心原理

ViewTreeLifecycleOwner 的核心原理是利用 View 的 setTag() 和 getTag() 方法。当一个 Activity 或 Fragment 的内容视图 (content view) 被设置时,ViewTreeLifecycleOwner 会将自身(一个 LifecycleOwner 实例)作为一个 tag 存入到视图层次结构的根视图中。

这样一来,视图层次结构中的任何一个子 View 都可以通过一个简单的静态方法来获取到它所属的 LifecycleOwner,而无需知道它的父 Activity 或 Fragment。

如何使用,后续将不再讲解

假设你有一个自定义 View,你想让它在屏幕上可见时开始执行动画,在不可见时暂停。在以前,你可能需要通过接口或回调,手动将 Activity 的 onResume() 和 onPause() 事件传递给这个 View,这会造成代码的耦合和复杂性。

有了 ViewTreeLifecycleOwner,事情就变得简单多了。

Kotlin 复制代码
// 1、获取LifecycleOwner: 在你的自定义 View中,
// 你可以通过静态方法 ViewTreeLifecycleOwner.get(view) 来获取它所属的 LifecycleOwner
val lifecycleOwner = ViewTreeLifecycleOwner.get(this)

// 2、拿到 lifecycleOwner 后,你就可以像在Activity或Fragment中一样,
// 添加一个 LifecycleObserver来监听生命周期事件
lifecycleOwner?.lifecycle?.addObserver(object : LifecycleObserver { 

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 
    fun startAnimation() {
    // 在宿主组件(如 Activity)恢复时开始动画 // 此时 View 必定是可见的 
    } 
    
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 
    fun stopAnimation() { 
    // 在宿主组件暂停时停止动画 // 此时 View 已经不可见 
    } 
 }

下面来具体说说LifecycleOwner

LifecycleOwner 的主要实现者

LifecycleOwner 是 Android 现代架构中非常核心的接口,它将生命周期抽象出来,并与组件解耦。

  • Activity 和 Fragment 是最常见的 LifecycleOwner,因为它们是 UI 界的直接代表。
  • Service 也可以成为 LifecycleOwner,用于后台任务。
  • ProcessLifecycleOwner 代表了整个应用进程的生命周期。
  • View 则通过 ViewTreeLifecycleOwner 机制,间接地获取 LifecycleOwner 的能力,实现更灵活的生命周期管理。

通过这些实现了 LifecycleOwner 的组件,开发者可以编写出更加健壮、易于维护、并且没有内存泄漏问题的代码。

Activity与Fragment是如何关联的

Activity 和 Fragment 与 LifecycleOwner 的关联,并不是简单的实现接口那么简单,而是一个精心设计的流程,以确保生命周期的正确传递和管理

Activity 与 LifecycleOwner 的关联

在现代 Android 中,Activity 与 LifecycleOwner 的关联主要依赖于 ComponentActivity。

ComponentActivity 的作用

ComponentActivity 是 androidx.activity 库中的一个基类,它是所有现代 Activity(包括 AppCompatActivity)的父类。它在内部实现了一些关键逻辑,其中就包括对 LifecycleOwner 的支持。

关联过程
  1. 实现 LifecycleOwner 接口 : ComponentActivity 本身就实现了 LifecycleOwner 接口,并持有一个 LifecycleRegistry 实例。LifecycleRegistry 是 Lifecycle 的具体实现,它负责存储当前生命周期状态,并向观察者分发事件。

  2. 通过 ReportFragment 传递事件 : ComponentActivity 在 onCreate() 方法中,会注册一个特殊的、不可见的 Fragment------ReportFragment 。这个 Fragment 的唯一任务就是监听 Activity 的生命周期回调(如 onResume, onPause 等),然后将这些回调事件转发给 LifecycleRegistry。

    • 当 Activity 的 onResume() 被调用时,ReportFragment 会捕获这个事件,并告诉 LifecycleRegistry,Lifecycle 的状态现在应该变为 RESUMED。
    • 当 Activity 的 onPause() 被调用时,ReportFragment 也会捕获它,并通知 LifecycleRegistry,状态应该变为 PAUSED。

这个机制巧妙地将 Activity 的生命周期回调与 LifecycleRegistry 解耦,ComponentActivity 只需要在 onCreate 中注册一次,之后所有的生命周期管理都由 ReportFragment 和 LifecycleRegistry 自动处理。

Fragment 与 LifecycleOwner 的关联

Fragment 与 LifecycleOwner 的关联比 Activity 稍微复杂一些,因为 Fragment 既有自己的生命周期,又有视图的生命周期。

Fragment 自身的 LifecycleOwner

Fragment 本身也实现了 LifecycleOwner 接口。它的生命周期从 onAttach() 开始,到 onDetach() 结束。Fragment 内部同样持有一个 LifecycleRegistry 实例,并在自己的生命周期回调方法中,手动更新 LifecycleRegistry 的状态。

例如,在 onStart() 中,Fragment 会调用 lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)。

viewLifecycleOwner 的关联

viewLifecycleOwner 是 Fragment 最关键的生命周期概念之一。它用于将 Fragment 的视图生命周期与一个独立的 LifecycleOwner 关联起来。

关联过程如下:
  1. 创建 viewLifecycleOwner : 在 Fragment 的 onCreateView() 方法执行完毕后,Fragment 会创建一个 LifecycleOwner 实例 ,并将其生命周期与视图的生命周期同步。这个 LifecycleOwner 就是 viewLifecycleOwner。
  2. 绑定到视图树 : Fragment 会利用 ViewTreeLifecycleOwner 这个工具,将新创建的 viewLifecycleOwner 绑定到视图层次结构的根视图上。它会调用 ViewTreeLifecycleOwner.set(view, viewLifecycleOwner)。
  3. 自动传递事件 : 当 Fragment 的视图被添加到窗口(onStart)或从窗口移除(onStop)时,Fragment 会自动更新 viewLifecycleOwner 的生命周期状态。当视图被销毁(onDestroyView)时,viewLifecycleOwner 的生命周期也会进入 DESTROYED 状态。

总结

  • Activity :通过 ComponentActivity 在 onCreate() 中注册一个 ReportFragment,由该 Fragment 监听 Activity 的生命周期并更新 LifecycleRegistry。
  • Fragment :既有自己的 LifecycleOwner,又通过 viewLifecycleOwner 专门管理视图的生命周期。viewLifecycleOwner 通过 ViewTreeLifecycleOwner 绑定到视图树,确保视图与生命周期的严格同步。

这种分层和代理的设计,使得开发者能够以统一的方式管理不同组件的生命周期,同时解决了 Fragment 视图生命周期与实例生命周期不一致的难题,这是现代 Android 架构健壮性的基石。

为什么要有fragment里要使用viewLifecycleOwner

通过上面的描述你应该能够大体知道原因了:viewLifecycleOwner 专门管理视图的生命周期。

在 Fragment 中观察 LiveData 时,传入 this 作为 LifecycleOwner 在某些情况下会导致问题。正确的做法是传入 viewLifecycleOwner。

  • Fragment 的生命周期比它的视图(View)的生命周期要长。一个 Fragment 可以被创建,但它的视图可能被销毁并重新创建多次(例如,在 BackStack 中进出)。

    如果你传入 this,观察者会绑定到 Fragment 整个生命周期。当 Fragment 的视图被销毁(onDestroyView 被调用)而 Fragment 本身仍然存在时,观察者仍然活跃。此时,LiveData 的更新会试图去更新一个已经不存在的视图,这可能导致 内存泄漏 或 空指针异常。

  • viewLifecycleOwner (Fragment 的视图生命周期) : Fragment 提供了一个特殊的属性 viewLifecycleOwner。它的生命周期范围精确地 与 Fragment 的视图生命周期相匹配。

    • 当 Fragment 的视图被创建时 (onCreateView),viewLifecycleOwner 的生命周期开始。
    • 当 Fragment 的视图被销毁时 (onDestroyView),viewLifecycleOwner 的生命周期结束。

    因此,在 Fragment 中,正确的观察方式是:

    Kotlin 复制代码
    viewModel.someLiveData.observe(viewLifecycleOwner, Observer { data ->
        // 更新 UI
    })

    这样做可以确保观察者只在视图存在且可见时才接收更新,并且在视图被销毁时自动移除观察者,从而避免了内存泄漏。

最后

系统通过上面的讲解能让你明白如何使用 Lifecycle,以及在哪些场景下需要使用。欢迎指正与收藏。谢谢

相关推荐
半摆烂日常26 分钟前
低代码平台API对接实践:接口鉴权与数据同步的完整实现
android·低代码·rxjava
事圆则缓1 小时前
volatile 使用场景全解析:它能保证什么,又解决不了什么
android
蒲公英内测分发2 小时前
智能投影仪参加海外展会,未上架的 Android 配套 App 怎么让客户限时试用?
android
ii_best2 小时前
按键精灵手机端开发安卓版实战:手写一个可最小化、可拖动的「运行日志悬浮窗」(附完整 源码 + 踩坑记录)
android·ios·智能手机·自动化·ai编程·按键精灵
终端安全笔记2 小时前
安卓做 MDM 管控,先分清三种注册入口
android·安全·智能手机
天远Date Lab2 小时前
零信任架构实战:基于天远全能消金报告(标准版)构建自动化骑手资信评估网关
运维·人工智能·架构·自动化
Shulex2 小时前
从问答到执行:跨境电商场景下抑制大模型幻觉与实现端到端任务闭环的工程架构实践
架构
乌萨达3 小时前
手机模拟器安卓怎么用?电脑安装应用、玩手游与账号同步指南
android·智能手机·电脑·雷电模拟器
美狐美颜SDK开放平台4 小时前
Android与iOS直播APP美颜有什么区别?视频美颜SDK开发详解
android·ios·音视频·视频美颜sdk
努力努力再努力wz4 小时前
【CUDA 入门系列】:Orin、GPU 并行执行模型与 CUDA 核心机制
架构