android Jetpack编写中的remember和rememberUpdatedState之间的区别?

92dk7w1h  于 2022-11-27  发布在  Android
关注(0)|答案(2)|浏览(703)

我很困惑,有人能解释一下两者之间的区别吗:

val variable by remember { mutableStateOf() }

val variable by rememberUpdatedState()

当我检查rememberUpdatedStates的源代码时,我实际上看到:remember { mutableStateOf() }

@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }
0x6upsns

0x6upsns1#

remember和rememberUpdatedStates之间的区别是:
记住了
请记住计算产生的值。计算只会在构成期间评估。重新构成永远会传回构成产生的值。
当您使用remember时,对重组的每个连续调用将仅返回在第一次调用remember期间最初计算的相同值。您可以将此视为只读状态,在重新计算将引用初始求值时,您不能在将来的引用中更新此状态。
记住更新状态
记住一个mutableStateOf,并在每次rememberUpdatedState调用重组时将其值更新为newValue。
当长期Lambda或对象运算式指涉撰写期间计算的参数或值时,应该使用rememberUpdatedState。重新组合会更新产生的状态,而不重新建立长期Lambda或对象,让该对象得以保存,而不需要取消和重新订阅,或重新启动可能会耗费大量资源或禁止重新建立和重新启动的长期作业。
在这里,我们可以预料到,有时候你的计算可能会花费一段时间,计算速度可能会相当慢。在这种情况下,你会得到最新的值,而不是lambda,它将影响每一次重组,这样你就可以引用计算产生的最新值。
通过使用此方法,您可以确保UI在每次重新组合时都得到更新,而无需重新创建长期有效的lambda或重新启动长期有效的操作(在记住方法的lambda回调期间可能会执行这些操作)。

vmjh9lq9

vmjh9lq92#

当你不想做一些繁重的计算/操作时,记住是需要的,当你的组合被重新组合时,另一方面,有时你的操作可能会改变,所以你需要做计算或更新记住的值,以便不能使用初始计算中的过时值。

fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }

rememberUpdatedState函数与使用remembermutableStatevalue改变时触发重组相同。

@Composable
private fun Calculation(input: Int) {
    val rememberUpdatedStateInput by rememberUpdatedState(input)
    val rememberedInput = remember { input }

    Text("updatedInput: $rememberUpdatedStateInput, rememberedInput: $rememberedInput")
}

var myInput by remember {
    mutableStateOf(0)
}

OutlinedButton(
    onClick = {
        myInput++

    }
) {
    Text("Increase $myInput")
}
Calculation(input = myInput)

这是一个非常基本的示例,说明values如何从remember和rememberUpdatedState更改为
更实际的例子是lambda
例如,假设您的应用有一个在一段时间后消失的LandingScreen。即使重新合成了LandingScreen,等待一段时间并通知已过去的时间不应重新启动的效果:

@Composable
fun LandingScreen(onTimeout: () -> Unit) {

    // This will always refer to the latest onTimeout function that
    // LandingScreen was recomposed with
    val currentOnTimeout by rememberUpdatedState(onTimeout)

    // Create an effect that matches the lifecycle of LandingScreen.
    // If LandingScreen recomposes, the delay shouldn't start again.
    LaunchedEffect(true) {
        delay(SplashWaitTimeMillis)
        currentOnTimeout()
    }

    /* Landing screen content */
}

在本例中,只调用了LaunchedEffect一次,但可以重新组合此LandingScreen函数,并且可能需要更改onTimeOut,因此使用rememberUpdatedState可确保在延迟后调用最新的onTimeout。

相关问题