Jetpack Compose 中的 Remember 和 RememberUpdatedState 之间的区别?

Has*_*ssa 25 android kotlin android-jetpack-compose compose-recomposition

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

val variable by remember { mutableStateOf() }
Run Code Online (Sandbox Code Playgroud)

val variable by rememberUpdatedState()
Run Code Online (Sandbox Code Playgroud)

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

@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }
Run Code Online (Sandbox Code Playgroud)

Thr*_*ian 25

remember当您不想在重组可组合项时进行一些繁重的计算/操作时,就需要使用它。另一方面,有时您的操作可能会发生变化,因此您需要进行计算或更新记住的值,以确保不使用初始计算中的过时值。

fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }
Run Code Online (Sandbox Code Playgroud)

rememberUpdatedStateremember功能与使用with相同,在更改时mutableState触发重组value

@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)
Run Code Online (Sandbox Code Playgroud)

这是一个非常基本的例子,展示了如何valuesrememberrememberUpdatedState改变。

一个更实际的例子是 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 */
}
Run Code Online (Sandbox Code Playgroud)

在此示例中LaunchedEffect,仅调用一次,但此 LandingScreen 函数可以重新组合,并且可能需要您进行更改onTimeOut,因此 usingrememberUpdatedState可确保onTimeout在延迟后调用最新的函数。


Jee*_*ede 20

RememberRememberUpdatedStates之间的区别是:

记住

记住计算产生的值。计算仅在合成期间进行评估。重组将始终返回组合产生的值。

当您使用 Remember 时,每次连续调用重组只会返回与第一次调用 Remember 期间最初计算的值相同的值。您可以将其视为只读状态,在重新计算将参考初始评估时无法更新未来的参考。


记住更新状态

记住 mutableStateOf 并在每次重新组合 RememberUpdatedState 调用时将其值更新为 newValue。

当组合期间计算的参数或值被长期存在的 lambda 或对象表达式引用时,应使用 RememberUpdatedState。重组将更新结果状态,而无需重新创建长期存在的 lambda 或对象,从而允许该对象持续存在,而无需取消和重新订阅,或者重新启动可能成本高昂或无法重新创建和重新启动的长期操作。

在这里,预计有时您的计算可能需要一段时间并且计算可能相当慢。在这种情况下,您将获得最新值,而不是 lambda,它将影响每次重组,以便您可以参考计算生成的最新值。

通过使用此方法,您可以确保每次重组都会更新您的 UI,而无需重新创建长寿命 lambda 或重新启动在 Remember 方法的 lambda 回调期间可能进行的长寿命操作。

  • @ArpitPatel如果您只需要直接在可组合项中使用该值,并且不需要在可能在组合范围之外执行的回调或lambda(例如:“LaunchedEffect”)中引用它,那么您可以只使用常规的“val”。但是,如果您需要确保回调或 lambda 始终具有最新状态,即使在组合外部调用它,也请使用“rememberUpdatedState”。 (2认同)