我有一个ViewModel,它产生一个这样的StateFlow:
private val _profiles = MutableStateFlow<List<ProfileSnap>>(listOf())
val profiles: StateFlow<List<ProfileSnap>>
get() = _profiles
值在另一个fun中更新:
private fun loadProfiles() = viewModelScope.launch {
_profiles.value = profileDao.getAll(profilesSearch, profilesSort)
}
最后,在Compose中,我列出了所有值(这是我的代码的简化版本):
@Composable
fun SetContent(viewModel: ProfilesViewModel){
val profiles = viewModel.profiles.collectAsState()
LazyColumn(
modifier = Modifier
.fillMaxHeight()
) {
itemsIndexed(items = profiles.value) { _, profile ->
Text(
text = "(${profile.profileId}) ${profile.label}",
modifier = Modifier
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
Log.d(TAG, "onLongPress: ${profile.profileId}")
},
onTap = {
Log.d(TAG, "onTap: ${profile.profileId}")
},
)
}
)
}
}
}
在开始时,当我到达列表片段并单击一个元素时,我得到了正确的对应profileId。但是,当我应用过滤器或更改列表排序时,调用loadProfiles()函数:
- 列表正确地相应地更改为新的过滤和/排序配置文件
- 当我点击一个元素时,我得到了错误的profileId,我似乎是以前的列表处置之一!
我做错了什么?档案不是最新的?但如果它们没有更新,为什么列表是"图形化的"?正确吗?下面是结果:
(1) A
-----
(2) B
-----
(3) C <== CLICK - onTap: 3 / LONGPRESS - onLongPress: 3
更改排序顺序:
(3) C
-----
(2) B
-----
(1) A <== CLICK - onTap: 3 [should has been 1] / LONGPRESS - onLongPress: 3 [should has been 1]
Thank you very much
您可以查看官方文档:
默认情况下,每个项的状态都是keyyed对的位置列表中项目的。但是,如果数据集发生变化,这可能会导致问题,因为改变位置的项目实际上会丢失任何记住的状态。想象一下
LazyRow
在LazyColumn
中的场景,如果行改变了项的位置,那么用户将失去在行中的滚动位置。
为了解决这个问题,您可以为每个项目提供一个稳定且唯一的密钥,为
key
提供一个块参数。提供一个稳定的键可以使项状态在数据集更改时保持一致:
LazyColumn() {
items(
items = profiles.value,
key = { profile ->
// Return a stable + unique key for the item
profile.profileId
}
) { profile ->
//....
}
}
根据Gabriele的提示,这是一个工作版本(我找不到items函数的相同签名):
LazyColumn() {
items(
count = profiles.value.size,
key = { index -> profiles.value[index].profileId }
) { index ->
val profile = profiles.value[index]
Item(profile)
Line()
}
}