jetpack compose 副作用 LaunchedEffect

📅 2026/8/4 1:51:48 👁️ 阅读次数 📝 编程学习
jetpack compose 副作用 LaunchedEffect

LaunchedEffect 跟组合走,进入启动、离开取消、key 变重启,解决的是"和组合生命周期同生同灭的协程副作用"这一类问题。

@Composable fun LaunchedEffect( key1: Any?, block: suspend CoroutineScope.() -> Unit ) { val applyContext = currentComposer.applyCoroutineContext remember(key1) { LaunchedEffectImpl(applyContext, block) } } private class LaunchedEffectImpl( private val parentContext: CoroutineContext, private val task: suspend CoroutineScope.() -> Unit ) : RememberObserver { private var scope: CoroutineScope? = null override fun onRemembered() { // ★ block 就是在这里被调用的 ★ scope = CoroutineScope(parentContext).apply { launch(block = task) // task == 你写的 block } } override fun onForgotten() { scope?.cancel() // 离开组合时取消 scope = null } override fun onAbandoned() { scope?.cancel() // remember 被丢弃时取消 scope = null } }

例子

一次性初始化

@Composable fun HomeScreen() { LaunchedEffect(Unit) { analytics.trackScreenView("home") // 埋点 sdk.initialize() // SDK 初始化 AppLogger.i("HomeScreen first composed") } HomeContent() }

响应式加载

@Composable fun DetailScreen(itemId: String, viewModel: DetailViewModel = viewModel()) { val uiState by viewModel.uiState.collectAsState() LaunchedEffect(itemId) { // itemId 变化时重新拉数据 viewModel.load(itemId) } when (uiState) { is Loading -> LoadingSpinner() is Success -> DetailContent((uiState as Success).data) is Error -> ErrorView((uiState as Error).message) } }

周期性更新(倒计时 / 轮询)

@Composable fun Countdown(seconds: Int, onTick: (Int) -> Unit, onEnd: () -> Unit) { LaunchedEffect(seconds) { repeat(seconds) { // 或者 while (isActive) { delay(1000); ... } delay(1000) onTick(seconds - it - 1) } onEnd() } } @Composable fun PollingCard(sessionId: String) { var status by remember { mutableStateOf(Status.PENDING) } LaunchedEffect(sessionId) { while (isActive) { // isActive 让取消能即时退出 status = api.poll(sessionId) if (status.isFinal()) break delay(2000) } } }

流订阅

@Composable fun MessageList(roomId: String, vm: ChatViewModel = viewModel()) { val messages by vm.messages(roomId).collectAsState() // 推荐:让 VM 暴露 StateFlow // 或者:直接在 Composable 里 collect(仅适合"纯展示流") val list = remember { mutableStateListOf<Message>() } LaunchedEffect(roomId) { chatService.observe(roomId).collect { msg -> list.add(msg) } } }