如何在Kotlin/Compose中确保仅运行一个LaunchedEffect
解决多定时器累加异常的方案
问题根源
- LaunchedEffect的key设置错误:用
true作为key是常量,只要showHome为true,每次重组都会启动新的LaunchedEffect协程,旧协程未被取消,导致多协程同时修改bean计数。 - updateAmount未实时更新:用
remember { mutableStateOf(...) }存储计算值,但未监听依赖的greenBeans等状态变化,导致数值固定不变,无法随解锁的bean类型更新每秒增量。 - 缺少循环逻辑:原代码里的LaunchedEffect只执行一次,要实现每秒更新需要在协程内添加循环+延迟逻辑。
修正代码
if (showHome) { // 用derivedStateOf自动计算实时增量,依赖变化时自动更新 val updateAmount by remember { derivedStateOf { greenBeans + (10 * kidneyBeans) + (100 * coffeeBeans) + (1000 * pintoBeans) + (10000 * chocolateBeans) + (100000 * jellyBeans) } } // 以showHome为key,showHome变为false时自动取消协程 LaunchedEffect(showHome) { // 循环每秒执行一次累加,协程取消时自动终止循环 while (isActive) { updateBeans { beans += updateAmount } delay(1000) } } }
关键说明
- derivedStateOf:专门用于基于其他State计算派生值,只有依赖的State变化时才会重新计算,既避免不必要的重组,又保证updateAmount实时准确。
- LaunchedEffect的key:用
showHome作为key,当showHome从true切换为false时,LaunchedEffect的协程会被自动取消,彻底停止定时器;当showHome再次变为true时,才会启动新的协程。 - while(isActive):
isActive是LaunchedEffect协程的内置属性,协程被取消时isActive变为false,循环自动终止,避免协程泄漏。
内容的提问来源于stack exchange,提问作者Mulhollandrl
相关产品推荐
相关产品推荐

