LaunchedEffect值捕获时机及两段代码执行结果差异问询
LaunchedEffect的值捕获时机与代码差异解析
核心规则:LaunchedEffect的值捕获逻辑
LaunchedEffect的协程代码块(block)捕获外部值的行为,取决于两个关键因素:
- 协程启动时机:协程只会在LaunchedEffect首次进入组合,或指定的
key发生变化时启动,启动时会捕获当时的外部值。 - 值的类型:如果捕获的是Compose的状态对象(比如
mutableIntStateOf返回的State实例),协程后续访问时会拿到该状态的最新值;如果是普通数据类型(如Int、String),则捕获的是启动时的快照,后续不会自动更新。
两段代码的差异分析
1. MainScreen2中的LaunchedEffect
LaunchedEffect(key1 = Unit, block = { delay(5000) Log.i("Launcher1", "1: $counter") })
key = Unit:Unit是固定值,所以这个LaunchedEffect只会在MainScreen2首次进入组合时启动一次协程。counter是mutableIntStateOf创建的状态对象:虽然协程启动时counter是0,但延迟5秒后访问counter时,会直接读取该状态对象的当前值。你在1秒内点击三次按钮,counter已经更新为3,所以最终Log输出1: 3。
2. test2中的LaunchedEffect
@Composable fun test2(count: Int) { LaunchedEffect(key1 = true, block = { delay(5000) Log.i("Launcher", "2: $count") }) }
key = true:同样是固定值,这个LaunchedEffect只会在test2首次进入组合时启动一次协程。count是普通Int参数:test2首次被调用时,count的值是0,协程启动时直接捕获这个0的快照。后续counter变化导致MainScreen2重组,test2会被重新调用传入新的count,但因为key没变化,旧协程不会被取消或重启,所以延迟5秒后输出的还是最初捕获的0。
验证修改(可选)
如果把test2中的LaunchedEffect的key改成count:
LaunchedEffect(key1 = count, block = { delay(5000) Log.i("Launcher", "2: $count") })
每次count变化时,旧协程会被取消,新协程启动并捕获当前的count值。此时点击三次按钮后,最后一次启动的协程会捕获3,延迟5秒后输出2: 3。
内容的提问来源于stack exchange,提问作者Programer
相关产品推荐
相关产品推荐

