我试图做一些列表操作,我遇到了问题的所有项目重组时,一个单一的项目更新。
https://prnt.sc/8_OAi1Krn-qg
我的模特;
data class Person(val id: Int, val name: String, val isSelected: Boolean = false)
@Stable
data class PersonsWrapper(val persons: List<Person>)
我的ViewModel和更新功能;
private val initialList = listOf(
Person(id = 0, name = "Name0"),
Person(id = 1, name = "Name1"),
Person(id = 2, name = "Name2"),
Person(id = 3, name = "Name3"),
Person(id = 4, name = "Name4"),
Person(id = 5, name = "Name5"),
Person(id = 6, name = "Name6"),
)
val list = mutableStateOf(PersonsWrapper(initialList))
fun updateItemSelection(id: Int) {
val newList = list.value.persons.map {
if (it.id == id) {
it.copy(isSelected = !it.isSelected)
} else {
it
}
}
list.value = list.value.copy(persons = newList)
}
和My可组合函数;
@Composable
fun ListScreen(personsWrapper: PersonsWrapper, onItemClick: (Int) -> Unit) {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = Modifier.fillMaxSize()
) {
items(personsWrapper.persons, key = { it.id }) {
ListItem(item = it, onItemClick = onItemClick)
}
}
}
compose_reports中的所有模型类看起来都很稳定;
第一个
当我想改变列表中单个项目的选中状态时,整个列表会被重新组合。我也尝试过使用kotlinx. collections中的ImmutableList和Persistant列表。但是问题没有解决。
列表操作时如何避免不必要的重组?
2条答案
按热度按时间inn6fuwd1#
MutableState使用结构相等来检查您是否使用新示例更新了state.value。每次您选择一个新项目时,您都会创建一个新的列表示例。
如果你在一个列表中添加、删除或更新一个条目,那么你可以使用
SnapshotStateList
来触发重新组合。SnapshotStateList是一个列表,它可以用时间复杂度O(1)来获得条目,而不是在最坏的情况下用O(n)来迭代整个列表。仅使用可变状态列表
结果是只有单个项目得到重组。
您可以将ViewModel with SnapshotState列表更新为
ListItem
可组合您的清单
我用来直观检查重组的代码。
使用视图状态
测试结果
并将ViewModel更新为
1000 ms和延迟是为了演示。在真实的的应用程序中,你将从REST或DB中获得数据。
显示列表或使用ViewState加载的屏幕
r3i60tvu2#
我认为这是因为你使用
.map {..}
,它创建了一个新的完整的列表集。返回一个列表,其中包含将给定的转换函数应用于原始集合中每个元素的结果。
通过这样做
您实际上是在创建一组全新列表,并将它们分配给LazyColumn,从而使其完全重新组合。
我建议如下:
使用
SnapshotStateList
(mutableStateListOf
)只需使用列表迭代器修改结构(在您的情况下)