提问人:Ayush Patel 提问时间:7/21/2023 更新时间:7/22/2023 访问量:120
更新 mutableStateList 中的项不会触发 UI 中的重组 (LazyColumn)
Updating item in a mutableStateList is not triggering recomposition in UI (LazyColumn)
问:
我一直在为这个问题挠头。 我有一个数据类,表示可以选择(或取消选择)的项目。
data class FilterItem(
val name: String,
val isSelected: Boolean
)
我在 ViewModel 中创建了一个 mutableStateList 项,它创建了一个列表,并且可以通过可组合项访问。
val filterList = mutableStateListOf<FilterItem>()
filterList.addAll(listOf(
FilterItem("ABC", isSelected = false),
FilterItem("DEF", isSelected = false)
))
我的可组合项访问列表 -
FilterLayout(
filterList = viewModel.filterList
)
@Composable
fun FilterLayout(
filterList: SnapshotStateList<FilterItem>
){
.....
itemsIndexed(filterList)) { index, it ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 15.dp)
.clickable {
setSelected(it.name)
},
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = it.name
)
Log.d("debug", "selected " + it.isSelected + " " + it.name)
Checkbox(
isSelected = it.isSelected,
onCheckedChange = {},
modifier = Modifier.size(25.dp)
)
}
}
}
这里的问题是,当单击一个项目时,会调用 setSelected,这会更新列表(直到这里才好)。当我打印消息时,更改会反映在 logcat 中。这意味着列表正在更新和重组。我可以看到该项目在日志中被选中,但 Ui 没有反映这一点。有时它确实会立即反映,有时我必须单击其他行来触发重组,然后它就会反射。
下面是我的更新功能 -
fun setSelected(name: String) {
viewModelScope.launch {
val index = filterList.indexOfFirst { name == it.name }
filterList[index] = filterList[index].copy(isSelected = !filterList[index].isSelected)
}
}
我尝试用 if-else 块替换复选框,仍然面临同样的问题 -if(it.isSelected) this icon else other icon
答:
0赞
Byte Code
7/21/2023
#1
mutableStateListOf 仅在添加、删除或替换新项时通知更改。试试这篇文章中的答案。
评论
0赞
Ayush Patel
7/21/2023
但正如您在我的 setSelected 函数中看到的那样 - 它正在替换当前项目。我尝试了日志记录,我可以看到该对象的 setSelected 之前和之后的不同哈希代码。
0赞
Byte Code
7/22/2023
fun setSelected(name: String) { filterList = filterList.map { if (it.name == name) it.copy(isSelected = !it.isSelected) else it }.toMutableStateList() }
如果你的清单不是很长,试试这个。
0赞
ObscureCookie
7/22/2023
#2
单击该复选框时,不会发生任何反应,因为它的 onCheckedChange 不执行任何操作。但是当单击该行时,它会成功更新。
@Composable
fun FilterLayout(
filterList: SnapshotStateList<FilterItem>,
setSelected: (String) -> Unit,
) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
itemsIndexed(filterList) { index, filterItem ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 15.dp)
.clickable {
setSelected(filterItem.name)
},
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = filterItem.name
)
Log.d("debug", "selected " + filterItem.isSelected + " " + filterItem.name)
Checkbox(
checked = filterItem.isSelected,
// set on checked change to update selected state
onCheckedChange = { setSelected(filterItem.name) },
modifier = Modifier.size(25.dp)
)
}
}
}
}
评论