android 将rememberSaveable与可变状态列表一起使用

n7taea2i  于 2022-12-31  发布在  Android
关注(0)|答案(3)|浏览(255)

我正在尝试添加一个可变的可打包对象列表到我的可组合对象中。我还希望能够向其中添加对象和从中删除对象。
目前我使用的是这样的东西:

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().
这意味着SnapshotStateListmutableStateListOf的结果)不可保存。
到目前为止,我能想到几种方法来解决这个问题:
1.实际实现SnapshotStateList的保护程序。
1.使用类似val namesState = rememberSaveable { mutableStateOf(listOf<String>()) }的东西,这确实可以完美地工作,但是更新列表需要设置值,这既慢又不方便(例如,namesState.value = namesState.value + "Joe"用于只添加一个元素)。
这两种方法对于一个看似很小的任务来说似乎都太复杂了。我想知道做我想做的事情的最好方法是什么。谢谢。

gmxoilav

gmxoilav1#

rememberrememberSaveable中不应有您担心丢失的数据:一旦Composable消失(准确地说,是从合成中消失),它就会被销毁。
如果您仍然对在rememberSaveable中存储mutableStateListOf感兴趣,我建议您按照错误建议为SnapshotStateList创建一个Saver

@Composable
fun <T: Any> rememberMutableStateListOf(vararg elements: T): SnapshotStateList<T> {
    return rememberSaveable(
        saver = listSaver(
            save = { stateList ->
                if (stateList.isNotEmpty()) {
                    val first = stateList.first()
                    if (!canBeSaved(first)) {
                        throw IllegalStateException("${first::class} cannot be saved. By default only types which can be stored in the Bundle class can be saved.")
                    }
                }
                stateList.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仍然限于可捆绑保存的类型,如StringInt等。如果您需要在其中存储自定义类型,则还需要修改Saver以保存/重新创建它。

klr1opcd

klr1opcd2#

我想出了这样的点子

val selectedLists: MutableList<String?> = rememberSaveable(
    saver = listSaver<MutableList<String?>, String?>(
        save = {
            if (it.isNotEmpty()) {
                it.toList()
            } else {
                listOf<String?>(null)
            }
        },
        restore = {
            it.toMutableStateList()
        }
    )
) {
    mutableStateListOf(*viewState.selectedLists.map { it.name }.toTypedArray())
}
oxiaedzo

oxiaedzo3#

您存储的数据类型必须可以保存在Bundle中,否则,您必须传入一个自定义saver对象。

相关问题