Jetpack Compose中rememberUpdatedState与mutableStateOf的区别及适用场景
关于rememberUpdatedState的疑问解答
一、它和不带remember的mutableStateOf本质不同
虽然你的示例里var2(不带remember的mutableStateOf)和var3(rememberUpdatedState)看起来值始终同步,但两者底层逻辑完全不一样:
var2 = mutableStateOf(derivedVar):每次TextChild重组时,都会创建全新的MutableState实例,初始值是当前重组时的derivedVar。旧实例会被丢弃,每次重组都是新对象。var3 = rememberUpdatedState(derivedVar):它会复用同一个MutableState实例,仅在每次重组时把实例的value更新为最新的derivedVar。实例从第一次重组就被remember保留,后续不会重新创建。
二、核心适用场景:在持久化副作用中获取最新值
rememberUpdatedState的关键作用,是解决副作用闭包捕获旧值的问题。比如使用LaunchedEffect、DisposableEffect这类仅在指定key变化时重启的副作用时,闭包默认会捕获副作用启动时的旧参数值,后续参数更新后闭包也拿不到新值。用rememberUpdatedState包裹参数,就能让闭包里始终拿到最新值。
举个对比示例:
@Composable fun TextChild(derivedVar: Int) { // 情况1:直接用derivedVar,LaunchedEffect启动后无法感知后续参数变化 LaunchedEffect(Unit) { while (true) { delay(1000) println("直接捕获的derivedVar:$derivedVar") // 永远是第一次传入的值 } } // 情况2:用rememberUpdatedState包裹,能拿到最新值 val latestDerivedVar = rememberUpdatedState(derivedVar) LaunchedEffect(Unit) { while (true) { delay(1000) println("最新的derivedVar:${latestDerivedVar.value}") // 参数更新后会打印新值 } } }
在你原示例里,因为TextChild每次重组都会重新执行整个函数体,所以var2和var3的value看起来一致,但放到不会重组的副作用闭包里,差异会立刻显现——var2每次重组生成新实例,副作用闭包如果捕获旧实例就拿不到新值;而var3的实例始终唯一,value会被更新,闭包里能拿到最新值。
三、原示例三个变量的差异总结
var1 by remember { mutableStateOf(derivedVar) }:第一次重组创建并remember住MutableState,后续重组不会重新初始化,value永远是第一次的derivedVar,不会更新。var2 = mutableStateOf(derivedVar):每次重组新建实例,value是当前重组时的derivedVar,但实例是临时的,无法在持久化逻辑中复用。var3 = rememberUpdatedState(derivedVar):复用同一个实例,每次重组更新value为最新的derivedVar,适合在持久化副作用中引用。
内容的提问来源于stack exchange,提问作者Robert Tirta
相关产品推荐
相关产品推荐

