关于 map 中不存在键的问题,正如您所说。因此,您需要告诉记住,待办事项是需要更新的键。如果你不想失去一部分的状态,记住你可以打开第二个。
在下面的代码中,我首先创建了地图并在周围放置了一个记忆以保持状态。其次,我创建了一个每次刷新 todos 时都会刷新的记忆。在那里,我合并了两个映射并将现有值或 false 关联为默认值。
/* Jetpack Compose Desktop but still applies to Android */
data class TODOItem(val id: Long, val content: String)
@ExperimentalAnimationApi
@ExperimentalMaterialApi
@Composable
fun TODOList(todos: List<TODOItem>) {
val expandedStates = remember { mutableStateMapOf<Long, Boolean>() }
remember(todos) {
if (expandedStates.isNotEmpty()) {
val updated = todos.map { todo -> todo.id }
val mergeMap = (expandedStates.keys + updated).associateWith{ expandedStates[it] ?: false }
expandedStates.clear()
expandedStates.putAll(mergeMap)
} else {
expandedStates.putAll(todos.associate { todo -> todo.id to false })
}
}
LazyColumn {
items(todos) { todo ->
Card(
onClick = {
expandedStates[todo.id] = expandedStates[todo.id]?.not() ?: true
}
) {
Column {
Text(text = "id ${todo.id}")
AnimatedVisibility(
visible = expandedStates[todo.id]!!
) {
Text(text = "content ${todo.content}")
}
}
}
}
}
}
@ExperimentalMaterialApi
@ExperimentalAnimationApi
fun main() {
Window {
val todos = remember { mutableStateOf(emptyList<TODOItem>()) }
var items = 0
LaunchedEffect(Unit) {
fixedRateTimer(period = 2000L) {
todos.value = if (todos.value.isEmpty()) {
items += 20
List(items) { TODOItem(it.toLong(), "content $it") }
} else emptyList()
}
}
TODOList(
todos = todos.value
)
}
}
注意:如果您有一个删除数据库中项目的查询,则 ID 仍然存在于 UI 中。
如果您的问题只需要您在一个空列表后更新一次,您可以从您的代码中传递记住一个键来更新。
val expandedStates = remember(todos) {
mutableStateMapOf(*todos.map { todo -> todo.id to false }.toTypedArray())
}