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


相关推荐
特立独行的猫a2 天前
从XML到Compose的UI变革:现代(2026)Android开发指南
android·xml·ui·compose·jetpack
stevenzqzq4 天前
compose中 Modifier的使用
compose
stevenzqzq4 天前
Slot API 设计模式
设计模式·compose
stevenzqzq5 天前
compose 中 Arrangement和Alignment比较
compose
stevenzqzq5 天前
compose 中 align和Arrangement的区别
android·compose
氦客12 天前
Android Compose : 解决列表滑动导致BottomSheet异常消失的问题
android·compose·滑动·lazygrid·bottomsheet·lazycolumn·异常消失
stevenzqzq12 天前
compose扩大子控件点击区域方法总结
compose
stevenzqzq12 天前
compose扩大子控件点击区域办法
compose
氦客13 天前
Android Compose : 仿IOS风格BottomSheet关闭效果:滑动到顶部,再次滑动才关闭
android·compose·bottomsheet·仿ios风格·底部弹框·滑动到顶部·再次滑动才关闭
stevenzqzq13 天前
Android 自定义View迁移Compose实战指南
android·compose