在 SnapshotStateList 中添加单个项目会导致所有可见项目重新组合

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

我有一个场景,我将项目添加到

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)
        }
    }
}
android kotlin android-studio android-jetpack-compose android-viewmodel
1个回答
0
投票

无论是否使用该键,您的代码都会跳过文本合成。要查看 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

但是,当您指定项目的键时,将跳过重组。您可以在布局检查器上检查它。

右侧的数字是跳过次数。

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