kotlin 我可以使用State〈ArrayList< T>>或State〈mutableListOf()>来观察Compose,以便在它们发生变化时触发重组吗?

shstlldc  于 2023-01-31  发布在  Kotlin
关注(0)|答案(2)|浏览(260)

以下内容来自article
1:我不完全理解是否可以使用State<ArrayList<T>>State<mutableListOf()>作为Compose观察的对象,以便在它们发生变化时触发重新组合?
2:我很奇怪为什么State<List<T>>和不可变的listOf()可以被Compose观察到在它们改变时触发重组,而实际上List<T>和不可变的listOf()是不可变的,你能给予我一些示例代码吗?
警告:使用可变对象(如ArrayList或mutableListOf())作为编写中的状态会导致用户在应用中看到错误或过时的数据。
不可观察的可变对象(如ArrayList或可变数据类)无法被Compose观察到,从而无法在它们发生更改时触发重新组合。
我们建议您使用可观察的数据保持器,如State和不可变的listOf(),而不是使用不可观察的可变对象。

图像

z9smfwbn

z9smfwbn1#

核心概念是
只有当可观察到的状态变化发生时,重组才会发生。
对于可变对象,我们可以选择使用add()remove()和其他方法,直接修改对象。
但是这个变化不会触发重组,因为这个变化是不可观察的。(对象示例没有变化)
即使对于可变对象,我们也可以通过将它们赋给一个新的对象示例来触发正确的重组。(对象示例被改变了)
因此,使用可变对象容易出错。
我们还可以看到由于这个问题而导致的lint错误。

另一方面,像list这样的不可变对象不能被修改,它们被一个新的对象示例所取代。
因此,它们是可观察的,并发生适当的重组。(对象示例被更改)
以此为例来理解概念。

@Composable
fun ComposeListExample() {
    var mutableList: MutableState<MutableList<String>> = remember {
        mutableStateOf(mutableListOf())
    }
    var mutableList1: MutableState<MutableList<String>> = remember {
        mutableStateOf(mutableListOf())
    }
    var arrayList: MutableState<ArrayList<String>> = remember {
        mutableStateOf(ArrayList())
    }
    var arrayList1: MutableState<ArrayList<String>> = remember {
        mutableStateOf(ArrayList())
    }
    var list: MutableState<List<String>> = remember {
        mutableStateOf(listOf())
    }
    
    Column(
        Modifier.verticalScroll(state = rememberScrollState())
    ) {
        // Uncomment the below 5 methods one by one to understand how they work.
        // Don't uncomment multiple methods and check.
        
        
        // ShowListItems("MutableList", mutableList.value)
        // ShowListItems("Working MutableList", mutableList1.value)
        // ShowListItems("ArrayList", arrayList.value)
        // ShowListItems("Working ArrayList", arrayList1.value)
        // ShowListItems("List", list.value)

        Button(
            onClick = {
                mutableList.value.add("")
                arrayList.value.add("")

                val newMutableList1 = mutableListOf<String>()
                mutableList1.value.forEach {
                    newMutableList1.add(it)
                }
                newMutableList1.add("")
                mutableList1.value = newMutableList1

                val newArrayList1 = arrayListOf<String>()
                arrayList1.value.forEach {
                    newArrayList1.add(it)
                }
                newArrayList1.add("")
                arrayList1.value = newArrayList1

                val newList = mutableListOf<String>()
                list.value.forEach {
                    newList.add(it)
                }
                newList.add("")
                list.value = newList
            },
        ) {
            Text(text = "Add")
        }
    }
}

@Composable
private fun ShowListItems(title: String, list: List<String>) {
    Text(title)
    Column {
        repeat(list.size) {
            Text("$title Item Added")
        }
    }
}

P.S:如果你有一个需要修改的项目列表,以及正确触发重组,请使用mutableStateListOf

2izufjch

2izufjch2#

我设法这样做:

@Composable
fun ComposeListExample(
    allObjects: List<Object>,
    selectedObjects: List<Object>
) {
    val selectedItems = remember {
        mutableStateListOf<Object>().apply { addAll(selectedObjects) }
    }
    Column {
        allObjects.forEach { item ->
            SomeView(
                title = item.title,
                onSelect = {
                    if (selectedItems.contains(item)) {
                        selectedItems.remove(item)
                    } else {
                        selectedItems.add(item)
                    }
                })
        }
    }
}

相关问题