当提供非状态对象时,compose 如何进行重组

Teh*_*Mir 1 android kotlin android-jetpack-compose composable

首先看下面的代码

class WellnessViewModel : ViewModel() {

    private val _tasks = getWellnessTasks().toMutableStateList()
    val tasks: List<WellnessTask>
        get() = _tasks
Run Code Online (Sandbox Code Playgroud)

现在,我将任务传递给 composeFunction,并且 _tasks 中的任何更改(添加或删除项目)都会导致 composeFunction 重新组合。但是这个东西究竟是如何工作的,因为我向该函数提供了非状态对象,如下代码所示。

@Composable
fun WellnessScreen(
    modifier: Modifier = Modifier,
    wellnessViewModel: WellnessViewModel = viewModel()
) {
    Column(
        modifier = modifier
    ) {
        StatefulCounter()
        WellnessTasksList(
            list = wellnessViewModel.tasks,
            onCloseTask = {
                wellnessViewModel.remove(it)
            },
            onCheckedTask = { task, checked ->
                wellnessViewModel.changeTaskChecked(task, checked)
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么它有效以及如何工作,对此需要一个简单的解释。

Thr*_*ian 7

但是这个东西究竟是如何工作的,因为我向该函数提供了非状态对象,如下代码所示

因为 SnapshotStateList 正是一个StateObject,并且使用新实例添加、删除或更新项目会触发重组。

@Stable
class SnapshotStateList<T> : MutableList<T>, StateObject 
Run Code Online (Sandbox Code Playgroud)

_tasks = getWellnessTasks().toMutableStateList()是一个SnapshotStateList. 如果您希望更改属性,则对该列表进行任何修改、更新都需要设置新项目,并会触发重组,因为它是 StateObject。这就是 SnapshotStateList 的问题,它会触发更改的项目的重组。您可以将其视为 mutableStateOf(list),但具有选择性重组,而不是传递重组每个项目的新列表。

此外,当 lambda 调用不稳定时,它会导致重组。

为什么可组合对象看似无状态(唯一传递的参数是函数,而不是状态),但会进行重组

您还可以查看这个答案,了解如何使用 SnapshotStateList、不稳定的 lambda 和传递稳定输入而不是不稳定的 List 来优化重组。

Jetpack Compose 惰性列在单个项目更新时重新组合所有项目