目录
一、副作用的概念
副作用是指发生在可组合函数作用域之外的应用状态变化。由于可组合项可能因重组而被频繁、无序地执行,理想情况下应保持无副作用。但当需要执行如显示弹窗、发起网络请求等操作时,必须使用专门的 Effect API 在受控环境中进行,以确保行为可预测且与可组合项的生命周期一致。
二、相关API
1.LaunchedEffect
📌 1)LaunchedEffect是什么
官方定义:一个可组合函数,用于在可组合项的生命周期内执行挂起函数。
通俗理解:它是一个“自带生命周期的协程启动器”。
🎯 2)LaunchedEffect的三种工作模式
模式1:跟随屏幕生命周期(永不重启)
kotlin
LaunchedEffect(Unit) { // Unit永远不会变
// 这个协程和可组合项同生共死
while (true) {
delay(1000)
// 每秒执行一次,直到屏幕销毁
}
}
适用场景:轮询、持续动画、WebSocket连接
模式2:响应变化重启
kotlin
LaunchedEffect(userId) { // userId变化时重启
// 旧的网络请求被取消
val userData = api.fetchUser(userId) // 挂起函数
// 用新数据更新界面
}
适用场景:依赖参数的网络请求、搜索防抖
模式3:条件执行(配合if)
kotlin
if (shouldLoad) {
LaunchedEffect(Unit) {
// 只有当shouldLoad为true时才执行
loadData()
}
}
// 当shouldLoad变false,效应退出组合,协程取消
适用场景:模态框出现时加载数据、条件性监听
💡 3)最易错的陷阱(必看!)
陷阱1:在LaunchedEffect里读状态
kotlin
var counter by remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
while (true) {
delay(1000)
println("计数:$counter") // ❌ counter永远是0!
// 因为LaunchedEffect启动时捕获了counter的初始值
}
}
解决方法:用rememberUpdatedState
kotlin
val currentCounter by rememberUpdatedState(counter)
LaunchedEffect(Unit) {
while (true) {
delay(1000)
println("计数:$currentCounter") // ✅ 每次都是最新的
}
}
2.rememberCoroutineScope
3.rememberUpdatedState
4.DisposableEffect
📌 1)DisposableEffect是什么?
官方定义:用于需要手动清理的副作用,当键变化或退出组合时执行清理操作。
通俗理解:它强制你写onDispose { },确保资源被正确释放。
5.SideEffect
🎯 1)SideEffect是什么?
官方定义:在每次成功重组后执行的副作用,用于将Compose状态同步到非Compose环境。
一句话理解:它是Compose的"状态同步器"——每次界面更新完,就自动通知外部世界。
SideEffect就像"状态广播员"——每次界面更新完,它就自动对外喊一嗓子:"最新状态来啦!"
6.produceState
🎯1) produceState是什么?
官方定义:一个将非Compose状态(如Flow、LiveData、回调)转换为Compose的State的API。
一句话理解:它是数据转换器——把外部世界的数据流,变成Compose界面能直接用的State!
2.与remember(带key)对比
| 对比维度 | produceState | remember (带key) |
|---|---|---|
| 本质 | 执行操作 + 返回State | 缓存值 + 返回任意类型 |
| 执行时机 | 进入组合或key变化时启动协程 | 进入组合或key变化时立即计算 |
| 返回值 | 永远是State<T> |
可以是任意类型 |
| 协程支持 | ✅ 支持挂起函数 | ❌ 不支持挂起 |
| 生命周期 | 有独立的协程生命周期 | 只是一个值 |
| 典型用途 | 异步数据加载 | 缓存计算结果 |
7.derivedStateOf (派生状态)
8.snapshotFlow
🎯 1)snapshotFlow是什么?
官方定义:一个将Compose的State对象转换为冷Flow的函数。
一句话理解:它是状态监听器——把Compose世界的状态变化,转换成Flow世界的数据流!
0 条评论