compose中 DisposableEffect和onDispose

跟进 定义 → 关系 → 触发时机 → 正确使用模式 → 常见坑 → MVI 场景 来讲清楚。


一、先给一句话结论

DisposableEffect 是"生命周期作用域"
onDispose 是"离开该作用域时的清理回调"

👉 两者不是同级概念


二、先把概念分清楚(非常重要)

1️⃣ DisposableEffect 是什么?

kotlin 复制代码
DisposableEffect(key) {
    // 初始化 / 注册逻辑

    onDispose {
        // 清理逻辑
    }
}

它本身代表:

"当这个 Composable 进入组合时执行一次,当离开或 key 变化时执行清理"


2️⃣ onDispose 是什么?

kotlin 复制代码
onDispose {
    // 清理资源
}

它只是一个回调函数

"当 DisposableEffect 被销毁时执行"

👉 onDispose 永远只能写在 DisposableEffect 里


三、生命周期触发时机(核心)

我们用一张表直接说明 👇

事件 DisposableEffect onDispose
首次进入组合 执行 effect 代码
普通重组 ❌ 不执行
key 发生变化 ❌(旧的 effect 销毁)
离开组合

👉 onDispose 的触发条件 = effect 生命周期结束


四、一个最直观的时间线(建议你在脑子里记住)

text 复制代码
Composable 进入组合
   ↓
DisposableEffect 执行(注册)
   ↓
多次重组(不影响)
   ↓
Composable 离开组合 / key 改变
   ↓
onDispose 执行(清理)

五、标准使用模式(99% 场景)

✅ 模板写法(直接记)

kotlin 复制代码
DisposableEffect(key) {
    // 1️⃣ 注册 / 初始化
    val resource = registerSomething()

    onDispose {
        // 2️⃣ 注销 / 清理
        unregister(resource)
    }
}

典型场景 1:注册监听

kotlin 复制代码
DisposableEffect(lifecycle) {
    val observer = LifecycleEventObserver { _, event ->
        Log.d("Lifecycle", "$event")
    }
    lifecycle.addObserver(observer)

    onDispose {
        lifecycle.removeObserver(observer)
    }
}

典型场景 2:系统资源(Receiver)

kotlin 复制代码
DisposableEffect(Unit) {
    val receiver = MyReceiver()
    context.registerReceiver(receiver, filter)

    onDispose {
        context.unregisterReceiver(receiver)
    }
}

六、key 的作用(非常关键)

kotlin 复制代码
DisposableEffect(userId) { ... }

行为规则:

  • userId 不变 → effect 一直存在

  • userId 变化 →

    1. 先调用旧的 onDispose
    2. 再执行新的 DisposableEffect

👉 key = 生命周期边界


七、为什么不用 LaunchedEffect 来做这些?

场景 LaunchedEffect DisposableEffect
异步任务
协程自动取消
资源注册释放
同步监听

👉 DisposableEffect 解决的是"资源对称性问题"


八、一个非常常见的反模式(一定要避开)

❌ 错误写法:只注册,不清理

kotlin 复制代码
DisposableEffect(Unit) {
    lifecycle.addObserver(observer)
}

👉 Lint 都会直接报警


❌ 错误写法:在 onDispose 里做初始化

kotlin 复制代码
DisposableEffect(Unit) {
    onDispose {
        initSomething() // ❌
    }
}

九、在 MVI + Compose 中的正确定位

Composable 只负责 UI 生命周期

  • ViewModel:业务生命周期
  • DisposableEffect:UI 资源生命周期

示例:绑定 UI 层事件

kotlin 复制代码
DisposableEffect(Unit) {
    viewModel.bindUi()

    onDispose {
        viewModel.unbindUi()
    }
}

十、再给一句"工程级总结"(很重要)

DisposableEffect 是"声明式生命周期",
onDispose 是"它的 onDestroy 回调"。


相关推荐
没有bug.的程序员10 天前
本地开发环境优化深度实战:Docker Compose 编排内核、依赖服务治理与极速环境搭建指南
运维·docker·容器·compose·本地开发·编排内核·依赖服务治理
stevenzqzq11 天前
ConstraintLayout写法和Box写法比较
compose
Jomurphys14 天前
Compose 调用 - 震动 LocalHapticFeedback
android·compose
特立独行的猫a16 天前
Kuikly多端框架(KMP)实战:KMP中的 Ktor 网络库的多端适配指南
android·网络·harmonyos·ktor·compose·kmp·kuikly
特立独行的猫a17 天前
腾讯Kuikly框架实战:基于腾讯Kuikly框架实现Material3风格底部导航栏
android·harmonyos·compose·kmp·实战案例·kuikly
stevenzqzq19 天前
Jetpack Compose Modifier 核心说明
compose
儿歌八万首22 天前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
stevenzqzq24 天前
Compose 中的状态可变性体系
android·compose
stevenzqzq24 天前
kotlin和compose中使用by
kotlin·compose
特立独行的猫a1 个月前
从XML到Compose的UI变革:现代(2026)Android开发指南
android·xml·ui·compose·jetpack