副作用 (Side Effects)
在 Compose 中,副作用是指发生在可组合函数作用域之外的应用状态变化。
1. 常用 Effect 概览
| API | 触发时机 | 典型用途 |
|---|---|---|
LaunchedEffect | 进入组合或 Key 变化 | 启动协程进行耗时操作(网络、延时) |
rememberCoroutineScope | 调用回调时 | 在 onClick 等事件中启动协程 |
DisposableEffect | 进入组合或 Key 变化 | 需要清理的操作(注册/注销监听) |
SideEffect | 每次重组成功后 | 与非 Compose 代码同步状态(日志、分析) |
derivedStateOf | 观察的状态变化时 | 过滤高频状态,优化性能 |
2. LaunchedEffect:协程入口
示例:三秒后自动跳转
kotlin
@Composable
fun WelcomeScreen(onTimeout: () -> Unit) {
// 只有在初次进入组合时运行
LaunchedEffect(Unit) {
delay(3000)
onTimeout()
}
Text("欢迎来到我的 App")
}3. rememberCoroutineScope:手动触发
场景区分
LaunchedEffect是自动的(生命周期驱动)。rememberCoroutineScope是手动的(用户交互驱动)。
kotlin
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Button(onClick = {
// 在回调中使用 scope 启动协程
scope.launch {
snackbarHostState.showSnackbar("操作成功")
}
}) {
Text("显示提示")
}4. derivedStateOf:性能优化
用于将一个高频变化的状态转换为一个低频状态。
经典案例
监听列表滚动:只有在列表滚动超过第一项时才显示“回到顶部”按钮。
kotlin
val listState = rememberLazyListState()
val showButton by remember {
derivedStateOf {
listState.firstVisibleItemIndex > 0
}
}5. 什么时候该用副作用?
规则
永远不要在 Composable 函数体中直接进行“写”操作(如修改全局变量、请求网络),因为重组会频繁触发这些代码。请务必将这些操作包裹在上述 Effect 中。