可组合项生命周期
上图描述了组合中可组合项的生命周期:进入组合,执行 0 次或多次重组,然后退出组合。在可组合项执行过程中,影响操作结果的可以认为是一种副作用,如在Composable中执行网络请求、Dialog弹窗、弹Toast、页面跳转等,不管重组多少次,有些操作只需要执行一次即可,如果多次执行就会出现意想不到的结果。针对上述情况,Compose 有一系列专门的副作用 API 来处理。
LaunchedEffect
LaunchedEffect 可以在可组合项的作用域内开启协程,如果副作用中需要处理异步相关的任务,就可以选择LaunchedEffect。
@Composable
@NonRestartableComposable
@OptIn(InternalComposeApi::class)
fun LaunchedEffect(
key1: Any?,
block: suspend CoroutineScope.() -> Unit
) {
val applyContext = currentComposer.applyCoroutineContext
remember(key1) { LaunchedEffectImpl(applyContext, block) }
}
LaunchedEffect 进入可组合项时,它会启动一个协程。当LaunchedEffect 退出组合时,协程也将会取消。LaunchedEffect() 中可以传入一个key,如果重组时key发生改变,现有协程会被取消,并在新的协程中启动新的挂起函数。
注:如果是LaunchedEffect(true) 或 LaunchedEffect(Unit), 可以保证LaunchedEffect()中的key永远不发生变化,从而保证后面的lambda不参与重组。
使用示例:
@Composable
fun MyScreen(
state: UiState<List<Movie>>,
scaffoldState: ScaffoldState = rememberScaffoldState()
) {
// 第一次组合时如果state.hasError为true,那么在LaunchedEffect开启协程并显示Snackbar;当重组state.hasError变为false后,协程结束,Snackbar也会消失
if (state.hasError) {
// 如果重组时scaffoldState.snackbarHostState发生变化,协程会被取消并重新创建并执行
LaunchedEffect(scaffoldState.snackbarHostState) {
// 展示Snackbar
scaffoldState.snackbarHostState.showSnackbar(
message = "Error message",
actionLabel = "Retry message"
)
}
}
Scaffold(scaf