SnapshotStateList 如何检测已发生更改?

How SnapshotStateList detects that a change has occurred?

提问人:progquester 提问时间:7/13/2023 最后编辑:progquester 更新时间:7/18/2023 访问量:180

问:

假设我有一个 Student 的 SnapshotStateList,并且 Student 的定义是:

data class Student<val id: Int, var name: String>

val students = mutableStateListOf(Student(0, "Aaron"))

我的 Jetpack 作曲想要在学生更改时重新作曲。

找到以下函数来触发它:

fun addStudent(name: String) {
    students.add(Student(students.size, "Bob"))
}
fun removeStudent(key: Int) {
    students.remove(key)
}
fun replaceStudent(key: Int, name: String) {
    val old = students[key]
    students[key] = Student(old.key, name)
}

但以下函数无法触发它:

fun modifyStudent(key: Int, name: String) {
    students[key].name = name
}

为什么,SnapshotStateList 如何检测发生了更改?

科特林 android-jetpack-compose 可变状态

评论


答:

1赞 chuckj 7/18/2023 #1

快照系统将检测自身的变化,而不是其中可变状态的变化。SnapshotStateList

代码,

fun replaceStudent(key: Int, name: String) {
    val old = students[key]
    students[key] = Student(old.key, name)
}

修改并被检测为更改。students

fun modifyStudent(key: Int, name: String) {
    students[key].name = name
}

修改快照系统未将其视为更改的某些对象的属性。nameStudent

我建议你让 immutable 而不是 mutable,Student

data class Student(val id: Int, val name: String)

然后需要修改更新学生。replaceStudent

或者,您可以更改为Student

class Student(val id: Int, name: String) {
    var name by mutableStateOf(name);
}

这将使可观察性并在属性更改时通知 Compose。Studentname

我建议将 immutable 设为不可变。Student

作为奖励,我建议你在这种情况下使用而不是,就好像你曾经在删除后调用学生上方的索引将不匹配到 .使用 a 将解决此问题。您还需要将 更改为不用作下一个,而是使用全局整数或全局原子(如果您是多线程的),因为现在,创建新学生将覆盖现有学生的数据,因为如果删除了任何学生,则会导致生成重复值。SnapshotStateMapSnapshotStateListremoveStudentkeystudentsSnapshotStateMapaddStudentsizeidkey

评论

0赞 progquester 7/18/2023
谢谢。该代码仅用于描述我的问题,实际上不会在产品中使用。我实际上试图弄清楚的是,在内部,SnapshotStateList 如何检查它是否已更改并像可写一样调用回调。
0赞 chuckj 7/21/2023
快照系统采用多版本并发控制算法,在修改数据之前,使用写入时复制的方式生成数据的快照本地可变副本。SnapshotStateList 在内部使用不可变数组,该数组使用允许副本增量的持久性数据结构。换句话说,它不会检测到更改。更改状态对象时,将生成副本。快照维护一组已复制的对象,并通知组合有关此集合的信息,并将重新组合读取集合中任何对象的任何函数。