尽管 RememberUpdatedState 尚未更改,但 LaunchedEffect 在配置更改时执行

Mic*_*ovo 6 android-jetpack-compose

如果我正确理解文档,如果 RememberUpdatedState 未更改,则 LaunchedEffect 不应再次运行。

如果我运行下面的代码,那么它不会按预期工作,并且该值会在轮换时再次更新。

如果没有 LaunchedEffect,则在配置更改时会记住 RememberSaveable,并且输入中的文本是正确的(如果我输入某些内容,它仍然存在)。这让我相信 RememberUpdatedState 也不应该改变,但它却被触发了。为什么?

我做错了什么还是这是一个错误?或者有更好的方法来做到这一点吗?

谢谢 :)

@Composable
fun ThingView(
    thingViewModel: ThingViewModel,
    id: String?
) {
    var thingName by rememberSaveable { mutableStateOf("") }
    val scope = rememberCoroutineScope()
    
    LaunchedEffect(rememberUpdatedState(newValue = thingName)) {
        scope.launch {
            id?.let {
                val thing = thingViewModel.getThing(id)
                thingName = thing.name
            }
        }
    }
    
    OutlinedTextField(
        value = thingName,
        onValueChange = { thingName = it },
        label = { Text("Name") }
    )
}
Run Code Online (Sandbox Code Playgroud)

编辑:

澄清一下,目标是允许用户在文本字段中输入文本,并且不会在旋转时清除该文本。这对于用户来说会非常烦人,而且可能不是他们所期望的。

use*_*881 5

我认为您所看到的是,LaunchedEffect当配置更改时,状态会在轮换时被清除。因此,我认为您无法提供任何价值作为阻止其运行的密钥。

我想到了两个选择。按照原始代码的风格,您可能会考虑仅LaunchedEffect在确定状态已更改时声明 。例如,您可以维护id可保存文件中最后看到的内容,例如lastId,并测试输入时的更改。lastId当然,它要求您最初有一个哨兵值。

@Composable
fun ThingView(
    thingViewModel: ThingViewModel,
    id: String?
) {
    var thingName by rememberSaveable { mutableStateOf("") }
    var lastId: String? by rememberSaveable { mutableStateOf(null) }
    val scope = rememberCoroutineScope()

    if (lastId != id) {
        lastId = id
        LaunchedEffect(id) {
            scope.launch {
                id?.let {
                    val thing = thingViewModel.getThing(id)
                    thingName = thing.name
                }
            }
        }
    }
    
    OutlinedTextField(
        value = thingName,
        onValueChange = { thingName = it },
        label = { Text("Name") }
    )
}

Run Code Online (Sandbox Code Playgroud)

另一个可能更传统的选项是使用ViewModel在配置更改之间保留状态。您可以更新每个 ViewModelonValueChange并将ViewModel当前值提供回OutlinedTextField. 在这种风格中,您可能不需要效果或协程。

最后说一下我的理解rememberUpdatedState。我认为它通常旨在允许长期存在的协程或回调引用可组合范围中变量的当前值,而不需要在每次状态更改时重新创建协程或回调。闭包似乎仅限于效果,并且它捕获创建时的值。我仍在努力更好地理解它。