我有一个 SnapshotStateMap,用于跟踪布局中的更新,该地图存储在视图模型中。
该网站名称为:
val roundState = viewModel.roundState
for (index in 0 until attempts) {
val state = roundState[index] ?: WordState.Empty
Row {
RoundWord(state, letters)
}
}
在我的程序中,每次只更改一项,所以基本上我的思路是: 我添加一个新状态或更新地图中的旧状态 -> 我将其传递给 RoundWord -> 如果没有索引状态,我以空状态传递 -> RoundWord Composable 依赖于状态来显示所需的 UI。
这是 RoundWord 的正文
@Composable
private fun RoundWord(
state: WordState,
letters: Int,
) {
when (state) {
is WordState.Progress -> ProgressWord(letters)
is WordState.Empty -> WordCells(letters)
is WordState.Resolved -> WordCells(letters) { WiPLetter(state.value.word[it]) }
}
}
据我所知,如果给定索引的 roundState 映射中没有状态,我提供空状态,该状态被定义为密封接口层次结构中的对象。相同的对象 -> 没有重组。但由于某种原因它每次都会重新组合。我已经这样做了几天了,尽管阅读了大量文档,但我看不到我在这里缺少的内容。为什么空状态会发生这种重组?
WordState 密封类层次结构包含类型为
List<T>
的属性。 Compose 不认为 List 是稳定类型,因此签名实际上类似于 unstable words: List<String>
。
Compose 编译器无法完全确定 List、Map 和 Set 等集合确实是不可变的,因此将它们标记为不稳定
这个问题有几个解决方案
@Stable
带注释的类中。只要您遵守@Stable
合同,这应该有效。SnapshotStateList
我认为最好的选择是提供一个稳定性配置文件,这使得可以将所有 Kotlin 集合注释为稳定。只要您尊重稳定性合同,这就有效,而稳定性合同恰好基本上是一组良好实践。