关于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这个抽象类。它是整个生命周期感知的核心,所有感知都是基于这个接口。

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

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

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

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 出现之前,我们通常只能通过 ActivityFragment 来获取生命周期对象。但在一些复杂场景下,比如自定义 ViewRecyclerView 中的列表项,我们希望这些视图也能感知生命周期,以便在适当的时机执行或停止某些操作。

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

核心原理

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

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

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

假设你有一个自定义 View,你想让它在屏幕上可见时开始执行动画,在不可见时暂停。在以前,你可能需要通过接口或回调,手动将 ActivityonResume()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 现代架构中非常核心的接口,它将生命周期抽象出来,并与组件解耦。

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

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

Activity与Fragment是如何关联的

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

Activity 与 LifecycleOwner 的关联

在现代 Android 中,ActivityLifecycleOwner 的关联主要依赖于 ComponentActivity

ComponentActivity 的作用

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

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

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

    • ActivityonResume() 被调用时,ReportFragment 会捕获这个事件,并告诉 LifecycleRegistryLifecycle 的状态现在应该变为 RESUMED
    • ActivityonPause() 被调用时,ReportFragment 也会捕获它,并通知 LifecycleRegistry,状态应该变为 PAUSED

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

Fragment 与 LifecycleOwner 的关联

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

Fragment 自身的 LifecycleOwner

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

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

viewLifecycleOwner 的关联

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

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

总结

  • Activity :通过 ComponentActivityonCreate() 中注册一个 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,以及在哪些场景下需要使用。欢迎指正与收藏。谢谢

相关推荐
叽哥1 小时前
flutter学习第 2 节:第一个 Flutter 应用
android·flutter
2501_916007471 小时前
iOS 文件管理实战指南 查看 App 数据与系统日志的完整方法
android·ios·小程序·https·uni-app·iphone·webview
VisuperviReborn1 小时前
打造自己的前端监控---前端性能监控
前端·javascript·架构
PetterHillWater1 小时前
Uber Eats优食如何删除上亿张商品重复图片数据
架构
余辉zmh2 小时前
【MySQL基础篇】:MySQL常用内置函数以及实用示例
android·mysql·adb
你我约定有三2 小时前
分布式微服务--Nacos 集群部署
分布式·微服务·架构
惺惺作态2 小时前
Android 项目构建编译概述
android
_祝你今天愉快2 小时前
Java Lock
android·java·后端
2501_915106323 小时前
iOS 内测上架流程详解:跨平台团队如何快速部署 TestFlight
android·ios·小程序·https·uni-app·iphone·webview
brzhang3 小时前
昨天我和同事聊聊架构这事儿,特别是怎么才能睡个好觉,有点点收获
前端·后端·架构