SnapshotStateList更新时如何更新原始列表

Ely*_*lye 0 android android-jetpack-compose

我在 Jetpack Compose 中有一个待办事项列表,显示在 LazyColumn 中。

data class TodoItem(val id: Int, val title: String, var urgent: Boolean = false)

val todoList = listOf(
    TodoItem(0, "My First Task", true),
    TodoItem(1, "My Second Task", true),
    TodoItem(2, "My Third Task"),
)

@Composable
fun Greeting(name: String) {
    val todoListState = remember {
        todoList.toMutableStateList()
    }
    LazyColumn(modifier = Modifier.fillMaxHeight()) {
        items(items = todoListState, itemContent = { item ->
            Row(modifier = Modifier.fillMaxWidth(),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    modifier = Modifier.weight(1f).padding(8.dp),
                    text = item.title)
                Checkbox(
                    checked = item.urgent,
                    onCheckedChange = {
                        val index = todoListState.indexOf(item)
                        todoListState[index] = todoListState[index].copy(urgent = it)
                        Log.d("Track", "$todoList")
                    }
                )
            }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

这是第一次

[TodoItem(id=0, title=My First Task, urgent=true), 
 TodoItem(id=1, title=My Second Task, urgent=true), 
 TodoItem(id=2, title=My Third Task, urgent=false)]
Run Code Online (Sandbox Code Playgroud)

我先更新为false后,那就是false了

[TodoItem(id=0, title=My First Task, urgent=false), 
 TodoItem(id=1, title=My Second Task, urgent=true), 
 TodoItem(id=2, title=My Third Task, urgent=false)]
Run Code Online (Sandbox Code Playgroud)

当我将第一个更新为 true 后,todoItem不再更改并保持为在我将第一个更新为 false 后,则它是 false

[TodoItem(id=0, title=My First Task, urgent=false), 
 TodoItem(id=1, title=My Second Task, urgent=true), 
 TodoItem(id=2, title=My Third Task, urgent=false)]
Run Code Online (Sandbox Code Playgroud)

我检查了todoListState(SnapshotStateList),它不再与todoList. 是什么原因造成的?如何修复它?

更新

要修复它,我可以使用

                Checkbox(
                    checked = item.urgent,
                    onCheckedChange = {
                        val index = todoListState.indexOf(item)
                        todoListState[index] = todoListState[index].copy(urgent = it)
                        todoList[index].urgent = it
                        Log.d("Track", "$todoList")
                    }
                )
Run Code Online (Sandbox Code Playgroud)

但这意味着我必须同时更改 2 项。我怎样才能只更改其中一个,然后同时更新两者?

Thr*_*ian 5

它没有更新的原因是 toMutableStateList 添加了列表项

fun <T> Collection<T>.toMutableStateList() = SnapshotStateList<T>().also { it.addAll(this) }
Run Code Online (Sandbox Code Playgroud)

您应该创建一个 SnapshotStateList 并添加、删除和更新此列表中的项目。您使用的方法不正确。

如果您希望创建包含初始项目的 SnapshotStateList,您可以使用

编辑

我错过了 SnapShotStateList 没有添加功能。

SnapShotState 可以与 addAll 一起使用,或者您需要将它们添加为项目而不使用

 val todoList = remember {
       mutableStateListOf().apply {
        add(TodoItem(id=0, title="My First Task", urgent=true))
        add(TodoItem(id=1, title="My Second Task", urgent=true))
        ...
    }
 }
Run Code Online (Sandbox Code Playgroud)

应该像 @Eye 的回答或那样

val todoList = mutableStateListOf().apply {
        addAll(initialList)
 }
Run Code Online (Sandbox Code Playgroud)

或者,如果列表是函数的参数或需要从列表中检索项目,则需要使用 addAll 或 toMutableStateList 但仅使用 SnapshotStateList 来更新项目。

Jetpack Compose 惰性列在单个项目更新时重新组合所有项目