Jetpack?lifecycle!!!

前言

平时写页面的时候,经常要在onStart开启轮询、定位、动画,再去onStop停止。所有逻辑写在 Activity/Fragment 里,代码臃肿,还很容易忘记释放资源引发内存泄漏。

Lifecycle 是 Jetpack 的基础组件,作用就是让普通类感知页面生命周期,把和生命周期绑定的业务逻辑抽离出去,实现解耦。

依赖引入

复制代码
dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.4"
}

核心概念

Lifecycle 基于观察者模式,三个核心角色:

  1. LifecycleOwner :生命周期持有者,拥有 lifecycle 对象。AppCompatActivity、Fragment 都实现了这个接口;Fragment 操作 View 相关逻辑要用 viewLifecycleOwner。
  2. Lifecycle:状态机,保存当前状态,分发生命周期事件。
  3. LifecycleObserver :观察者,接收生命周期回调。
    • DefaultLifecycleObserver:推荐使用,直接重写对应生命周期方法
    • LifecycleEventObserver:接收原始 Event 事件,自己判断处理

状态流转: INITIALIZED → CREATED → STARTED → RESUMED → DESTROYED

事件: ON_CREATE、ON_START、ON_RESUME、ON_PAUSE、ON_STOP、ON_DESTROY

示例 1:DefaultLifecycleObserver

写一个轮询工具类,页面可见自动开启,不可见自动停止:

复制代码
class PollingManager : DefaultLifecycleObserver {
    private val handler = android.os.Handler(android.os.Looper.getMainLooper())
    private var runnable: Runnable? = null

    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)
        startPoll()
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        stopPoll()
    }

    private fun startPoll() {
        runnable = Runnable {
            println("轮询执行...")
            handler.postDelayed(runnable!!, 2000)
        }
        handler.post(runnable!!)
    }

    private fun stopPoll() {
        runnable?.let { handler.removeCallbacks(it) }
    }
}

在 Activity 中注册:

复制代码
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        lifecycle.addObserver(PollingManager())
    }
}

Fragment 中,和 View 相关的监听一定要用viewLifecycleOwner:

复制代码
viewLifecycleOwner.lifecycle.addObserver(PollingManager())

示例 2:LifecycleEventObserver 接收原始事件

适合需要统一处理多个生命周期事件的场景:

复制代码
class LifecycleLogObserver : LifecycleEventObserver {
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        when (event) {
            Lifecycle.Event.ON_CREATE -> println("ON_CREATE")
            Lifecycle.Event.ON_START -> println("ON_START")
            Lifecycle.Event.ON_RESUME -> println("ON_RESUME")
            Lifecycle.Event.ON_PAUSE -> println("ON_PAUSE")
            Lifecycle.Event.ON_STOP -> println("ON_STOP")
            Lifecycle.Event.ON_DESTROY -> println("ON_DESTROY")
            else -> {}
        }
    }
}

注册方式一样:

复制代码
lifecycle.addObserver(LifecycleLogObserver())

示例 3:ProcessLifecycleOwner 监听 App 前后台

监听整个 App 的前台、后台状态,全局使用:

复制代码
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)
        println("App 进入前台")
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        println("App 退到后台")
    }
})

注意:onStart = App 至少有一个页面可见;onStop = 所有页面全部不可见。

搭配协程:lifecycleScope + repeatOnLifecycle

lifecycle-ktx 提供的协程扩展,底层依赖 Lifecycle,页面销毁自动取消协程,不会泄漏:

复制代码
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        // 页面处于 STARTED 状态时运行,PAUSE 自动挂起,DESTROY 自动取消
    }
}

Fragment 同样优先用 viewLifecycleOwner:

复制代码
viewLifecycleOwner.lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        
    }
}

适用场景

  • 定时轮询、WebSocket、蓝牙、传感器、定位
  • 动画、播放器:页面可见播放,不可见暂停
  • 页面埋点统计,逻辑抽离
  • SDK 内部感知宿主生命周期,不用业务手动释放

避坑总结

  1. Fragment UI 逻辑使用 viewLifecycleOwner,不要直接用 fragment.lifecycle,二者生命周期不同;
  2. Lifecycle 只会分发回调,不会自动帮你取消任务、关闭线程,释放资源代码需要自己写;
  3. 一个 Observer 不要同时 add 给多个 LifecycleOwner;
  4. 配置变更(屏幕旋转)Activity 会重建,Lifecycle 会走完整销毁重建;长任务搭配 ViewModel;

和其他组件的关系

  • Lifecycle:感知生命周期,分发状态事件
  • ViewModel:独立于页面生命周期,屏幕旋转不销毁
  • LiveData:自带 Lifecycle 感知,只有活跃状态的观察者接收数据回调

小结

Lifecycle 的核心就是解耦。把绑定生命周期的业务从 Activity/Fragment 剥离为独立可复用类,代码更清爽,减少内存泄漏,也是 LiveData、Navigation 等 Jetpack 组件的底层基石。

相关推荐
苦瓜花1 小时前
Hilt用使用及原理
android
深度学习04072 小时前
MySQL InnoDB Cluster 部署完整文档
android·mysql·adb
邪修king3 小时前
Re:Linux系统篇(三十七):进程间通信Chapter4:System V 共享内存深度解析:为什么它是最快的 IPC?
android·linux·运维
用户337922545683 小时前
Kiora SDK:在 Android 上组织端侧模型、工具与 A2A 协作
android
洞见前行3 小时前
你在 XML 时代学的渲染优化,进了 Compose 大多不再是重点——Recomposition 才是新的战场
android
ii_best4 小时前
按键精灵手机助手 v5.2.1 实测:inputText 逐字延时 + 调试面板多行复制,安卓脚本开发的两个输入痛点一次解决
android·开发语言·智能手机·自动化·ai编程·按键精灵
hunterandroid4 小时前
OkHttp 源码解析:拦截器链、连接池与缓存策略的设计精髓
android
蒲公英内测分发4 小时前
智能手环出海测试,海外合作方分散在不同国家,Android 测试包怎么持续分发和更新?
android·前端·人工智能·测试工具·智能手表
朱涛的自习室4 小时前
高价软件已死,我让 AI 开启了「平替计划」(Day 7 / 7)
android·前端·github