我的布局中发生了冗余重组。为什么即使输入没有改变它也会重新组合?

问题描述 投票:0回答:1

我有一个 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 映射中没有状态,我提供空状态,该状态被定义为密封接口层次结构中的对象。相同的对象 -> 没有重组。但由于某种原因它每次都会重新组合。我已经这样做了几天了,尽管阅读了大量文档,但我看不到我在这里缺少的内容。为什么空状态会发生这种重组?

android kotlin android-layout android-jetpack-compose compose-recomposition
1个回答
0
投票

WordState 密封类层次结构包含类型为

List<T>
的属性。 Compose 不认为 List 是稳定类型,因此签名实际上类似于
unstable words: List<String>

Compose 编译器无法完全确定 List、Map 和 Set 等集合确实是不可变的,因此将它们标记为不稳定

这个问题有几个解决方案

  • 可以将 List 类型包装在
    @Stable
    带注释的类中。只要您遵守
    @Stable
    合同,这应该有效。
  • 使用 Kotlinx 不可变集合(它们看起来已被放弃)
  • 使用被认为稳定的
    SnapshotStateList

我认为最好的选择是提供一个稳定性配置文件,这使得可以将所有 Kotlin 集合注释为稳定。只要您尊重稳定性合同,这就有效,而稳定性合同恰好基本上是一组良好实践。

© www.soinside.com 2019 - 2024. All rights reserved.