kotlin 在重组方面,使用SnapshotStateList< T>优于State〈List有什么好处< T>吗?

np8igboo  于 2023-04-21  发布在  Kotlin
关注(0)|答案(1)|浏览(192)

在jetpack compose中,我们可以使用collectAsState()MutableStateFlow<T>转换为State<T>,并且通过委托by可以直接将T分配给变量。
现在,据我所知,如果我使用MutableState<T>MutableStateFlow<T>来保存状态,性能方面并不重要。但是对于List类型,似乎没有特殊版本的Flow,即,如果你真的需要,你可以使用Flow<List<T>,我已经看到使用了大部分时间。然后,如果你在Flow<List<T>上应用collectAsState(),你会得到State<List<T>
现在,如果我理解正确的话,即使单个值被更改在列表中添加(添加、移除、修改)的列表项UI组件,整个列表状态将被认为是新的,因此 * 所有 * 相应的列表项UI组件将被重新组合。或者,Jetpack compose对State<List<T>有一些内部优化,可以防止这些类型的无用重组,我不应该担心它。

vsmadaxz

vsmadaxz1#

根据我的测试,LazyColumn将重组项目,只要你提供的关键,即使它是从State<List<T>
我的测试样本:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TestSampleTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    val vm: SimpleViewModel = viewModel()
                    val list by vm.list.collectAsState()
                    SimplePage(
                        list = list,
                        onClick = {
                            vm.add()
                            vm.shuffle()
                        },
                    )
                }
            }
        }
    }
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SimplePage(
    list: List<Int>,
    onClick: () -> Unit,
) {

    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        LazyColumn(
        ) {
            items(
                list,
                key = { it }
            ) {
                Text(
                    modifier = Modifier.animateItemPlacement(),
                    text = it.toString()
                )
            }
        }
        Button(onClick = onClick) {
        }
    }

}

class SimpleViewModel : ViewModel() {
    //    val list = MutableStateFlow(listOf(1, 5, 8, 3, 7, 6))
    val list = MutableStateFlow(listOf(0))

    fun shuffle() = list.update {
        it.toMutableList().apply {
            shuffle()
        }
    }

    fun add() = list.update {
        it.toMutableList().apply {
            add(max() + 1)
        }
    }
}

在这里,Modifier.animateItemPlacement()只有在确保key唯一而不是位置的情况下才有效。key本身确保同一项不会重新组合。https://stackoverflow.com/a/70596559/13519865
https://stackoverflow.com/a/68794279/13519865
最后,animateItemPlacement工作,因此密钥使用得很好。
因此,我们可以放心地假设,我们可以使用State<List<T>来获得它的Flow操作优势,而无需过多考虑重组成本。

相关问题