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 回调"。


相关推荐
le1616167 天前
Android Compose——尺寸修饰符的调用顺序构成的不同尺寸约束效果
android·compose·modifier
le1616168 天前
Android Compose Modifier修饰符
android·compose·modifier
小书房8 天前
Android UI为什么由XML转向Compose
xml·ui·compose·声明式ui
le1616169 天前
Android Compose基础布局——从传统XML的视角切入了解
xml·compose
赏金术士14 天前
企业级 Jetpack Compose 项目(入门版)最佳结构
android·kotlin·compose
Jomurphys15 天前
Compose 调用 - 液态玻璃 Backdrop
android·compose
氦客18 天前
Android Compose 图层的合成 : BlendMode
android·compose·jetpack·layer·blendmode·graphics·图层的合成
赏金术士19 天前
第六章:UI组件与Material3主题
android·ui·kotlin·compose
赏金术士19 天前
Jetpack Compose 底部导航实战教程(完整版)
android·kotlin·compose
程序员煊子20 天前
用 Cursor 从零搭一个 Compose 本地记账 App:实战记录与源码解析
android·kotlin·compose·cursor