首页 > 解决方案 > 将 rememberSaveable 与 mutableStateListOf 一起使用

问题描述

我正在尝试将可变的可打包对象列表添加到我的可组合项中。我还希望能够向其中添加对象和从中删除对象。

目前我正在使用这样的东西:

val names = remember { mutableStateListOf<String>() }

names.add("Bill")
names.remove("Bill")

现在我希望这个列表能够在配置更改后继续存在,因此使用rememberSaveable. 也许是这样的:

val names = rememberSaveable { mutableStateListOf<String>() }

names.add("Bill")
names.remove("Bill")

但这不起作用,它会引发以下异常: androidx.compose.runtime.snapshots.SnapshotStateList cannot be saved using the current SaveableStateRegistry. The default implementation only supports types which can be stored inside the Bundle. Please consider implementing a custom Saver for this class and pass it to rememberSaveable().

这意味着,SnapshotStateList(的结果mutableStateListOf)是不可保存的。

到目前为止,我可以想到几种解决方法:

  1. 实际上为SnapshotStateList.
  2. 使用类似val namesState = rememberSaveable { mutableStateOf(listOf<String>()) }. 这确实可以完美地工作,但是更新列表需要设置值,这既慢又不方便(例如namesState.value = namesState.value + "Joe",仅添加单个元素)。

对于看似很小的任务,这两种方法似乎都太复杂了。我想知道做我想做的最好的方法是什么。谢谢。

标签: androidandroid-jetpack-compose

解决方案


里面应该没有数据remember或者rememberSaveable你害怕丢失:一旦你的视图消失,它就会被破坏。在这种情况下考虑使用视图模型。


如果您仍然对存储mutableStateListOf在里面感兴趣rememberSaveable,我建议您按照您的错误建议并创建一个Saverfor SnapshotStateList

@Composable
fun <T: Parcelable> rememberMutableStateListOf(vararg elements: T): SnapshotStateList<T> {
    return rememberSaveable(
        saver = listSaver(
            save = { it.toList() },
            restore = { it.toMutableStateList() }
        )
    ) {
        elements.toList().toMutableStateList()
    }
}

然后你可以像这样使用它:

val names = rememberMutableStateListOf<String>()
LaunchedEffect(Unit) {
    names.add("Bill")
}
Text(names.joinToString { it })

此示例的预期行为:每次旋转设备时 - 都会添加一个元素。

不要像添加和删除项目时那样在可组合项中使用任何状态修改。你应该只在side-effects中这样做,就像我在这里做的那样LaunchedEffect,或者回调,比如onClick.

请注意,saveableMutableStateListOf它仍然仅限于 Bundle-saveable 类型,例如String,Int等。如果您需要在其中存储自定义类型,您也需要修改Saver以保存/重新创建它。


推荐阅读