当实时数据更改时,Android Compose 惰性列不会更新

Osc*_*tor 1 android-livedata android-jetpack android-jetpack-compose lazycolumn

我有一个项目列表,其中每个项目都有一个复选框。复选框的状态需要存储在 中,viewmodel并且最好中的列表viewmodel应该是唯一的事实来源。

@Composable
fun Screen(viewModel: ViewModel) {
    val list by viewModel.items.observeAsState()

    LazyColumn {
        list?.let { items ->
            items(items) { item -> 
                ListItem(
                    text = {
                        Text(item.name)
                    },
                    secondaryText = {
                        Text(item.phoneNumber)
                    },
                    icon = {
                        Checkbox(
                            modifier = Modifier.padding(8.dp),
                            checked = item.selected,
                            onCheckedChange = {
                                //TODO

                            }
                        )
                    }
                )
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试item.selected通过更新回调中的列表(MutableLiveData<List<Object>>in viewmodel)来更新onCheckedChange,但 UI 没有更新。如果我向下滚动然后向上滚动,用户界面会更新,并且该复选框似乎已被选中。为什么不更新?

Phi*_*hov 11

MutableLiveData对它所持有的物体一无所知。当某些内部对象属性更新时,它无法向您发送新值。

要使用实时数据解决此问题,您需要为项目设置新值,设置相同的值就足够了:

fun setSelected(index: Int, selected: Boolean) {
    items.value!![index].selected = selected
    items.value = items.value
}
Run Code Online (Sandbox Code Playgroud)

但如果您没有LiveData被其他依赖项绑定,我建议您不要使用它。mutableStateListOf与 immutable 一起使用data class要干净得多:

data class Object(val selected: Boolean)

class VM: ViewModel() {
    val items = mutableStateListOf<Object>()

    fun setSelected(index: Int, selected: Boolean) {
        items[index] = items[index].copy(selected = selected)
    }
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都需要对象索引,可以通过以下方式获取它itemsIndexed

val list = viewModel.items
LazyColumn {
    itemsIndexed(list) { index, item -> 
        // ...
        onCheckedChange = {
            viewModel.setSelected(index, it)
        }
    // ...
    }
}
Run Code Online (Sandbox Code Playgroud)