我有一个场景,我将项目添加到
SnapshotStateList<T>
内的 ViewModel
。此项目列表在 UI 中使用 LazyColumn
显示。
这是我的 ViewModel 类
class MainViewModel(application: Application) : AndroidViewModel(application) {
val data = mutableStateListOf<String>()
init {
viewModelScope.launch { loadData() }
}
private suspend fun loadData() {
// I am adding items after a delay to simulate
// items getting added from a flow/other sources
delay(2000L)
data.add(sampleText(1))
delay(2000L)
data.add(sampleText(2))
delay(2000L)
data.add(sampleText(3))
delay(2000L)
data.add(sampleText(4))
delay(2000L)
data.add(sampleText(5))
}
private fun sampleText(id: Int): String = "Sample Text $id"
}
UI 由单个
LazyColumn
可组合组件组成。
@Composable
fun HomeScreen(viewModel: MainViewModel = viewModel()) {
TextList(textItems = viewModel.data)
}
@Composable
fun TextList(textItems: List<String>) {
LazyColumn {
items(textItems, key = { it.hashCode() }) {
println("TextList: Composing Text = $it")
Text(text = it)
}
}
}
我希望在每个项目添加到列表时看到
println()
行。然而,这是我在日志中看到的:
2023-08-12 21:55:30.352 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:30.895 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:30.905 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:32.899 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:32.902 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:32.912 29930-29930 System.out I TextList: Composing Text = Sample Text 3
2023-08-12 21:55:34.918 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:34.921 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:34.923 29930-29930 System.out I TextList: Composing Text = Sample Text 3
2023-08-12 21:55:34.931 29930-29930 System.out I TextList: Composing Text = Sample Text 4
2023-08-12 21:55:36.919 29930-29930 System.out I TextList: Composing Text = Sample Text 1
2023-08-12 21:55:36.922 29930-29930 System.out I TextList: Composing Text = Sample Text 2
2023-08-12 21:55:36.925 29930-29930 System.out I TextList: Composing Text = Sample Text 3
2023-08-12 21:55:36.931 29930-29930 System.out I TextList: Composing Text = Sample Text 4
2023-08-12 21:55:36.943 29930-29930 System.out I TextList: Composing Text = Sample Text 5
我很困惑为什么每次将新项目添加到列表中时,所有先前添加的项目都会重新组合?
这似乎与 Jetpack Compose 惰性列在单个项目更新时重新组合所有项目有关,但该解决方案在这里没有帮助。
编辑#1: 正如 CommonsWare 所建议的,我确实展平了 UI 并移动了
TextList
但结果没有改变
@Composable
fun HomeScreen(viewModel: MainViewModel = viewModel()) {
LazyColumn {
items(viewModel.data, key = { it.hashCode() }) {
println("TextList: Composing Text = $it")
Text(text = it)
}
}
}
无论是否使用该键,您的代码都会跳过文本合成。要查看 LazyColumn 中该键的效果,请稍微修改一下代码。
class MainViewModel(application: Application) : AndroidViewModel(application) {
val data = mutableStateListOf<String>()
init {
viewModelScope.launch { loadData() }
}
private suspend fun loadData() {
// I am adding items after a delay to simulate
// items getting added from a flow/other sources
delay(2000L)
data.add(sampleText(1))
delay(2000L)
data.add(sampleText(2))
delay(2000L)
data.add(sampleText(3))
delay(2000L)
data.add(sampleText(4))
delay(2000L)
data.add(0 ,sampleText(5)) // add Sample Text 5 at the index 0
}
private fun sampleText(id: Int): String = "Sample Text $id"
}
如果您不在项目上使用任何键,代码将不会重新组合文本。添加示例文本 5 后,将会发生重组。
Sample Text 1 // this will be recomposed to Sample Text 5
Sample Text 2 // this will be recomposed to Sample Text 1
Sample Text 3 // this will be recomposed to Sample Text 2
Sample Text 4 // this will be recomposed to Sample Text 3
// a new Text will be created as Sample Text 4
但是,当您指定项目的键时,将跳过重组。您可以在布局检查器上检查它。
右侧的数字是跳过次数。