英文:
How SnapshotStateList detects that a change has occurred?
问题
假设我有一个用于学生的SnapshotStateList,并且学生的定义如下:
data class Student(val id: Int, var name: String)
val students = mutableStateListOf(Student(0, "Aaron"))
我的Jetpack Compose希望在学生列表发生变化时重新组合。
我找到了以下函数来触发它:
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.id, name)
}
但以下函数不能触发它:
fun modifyStudent(key: Int, name: String) {
students[key].name = name
}
为什么?SnapshotStateList如何检测到变化发生了?
英文:
Suppose I have a SnapshotStateList for Student, and the definition of Student is:
data class Student<val id: Int, var name: String>
val students = mutableStateListOf(Student(0, "Aaron"))
My Jetpack compose in wants to recompose when students changes.
Found the following function to trigger it:
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)
}
But the following function cannot trigger it:
fun modifyStudent(key: Int, name: String) {
students[key].name = name
}
Why, how does SnapshotStateList detect that a change has occurred?
答案1
得分: 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
}
修改了某些Student
对象的name
属性,但快照系统不会将其视为更改。
我建议您将Student
设计为不可变的,而不是可变的,
data class Student(val id: Int, val name: String)
然后,replaceStudent
将需要修改学生。
或者,您可以将Student
更改为,
class Student(val id: Int, name: String) {
var name by mutableStateOf(name);
}
这将使Student
可观察,并在name
属性更改时通知 Compose。
我建议将Student
设计为不可变的。
作为额外建议,我建议您在这种情况下使用 SnapshotStateMap
而不是 SnapshotStateList
,因为如果您在删除学生后调用removeStudent
,则学生的key
将不匹配students
中的索引。使用 SnapshotStateMap
可以解决此问题。此外,您还需要更改addStudent
,不要使用 size
作为下一个 id
,而应使用全局整数或全局原子(如果多线程)作为下一个 id
,因为现在,创建新学生将覆盖现有学生的数据,因为它会生成重复的 key
值,如果删除了任何学生,就会导致这种情况。
英文:
The snapshot system will detect changes in SnapshotStateList
itself, not in changes to mutable state within it.
The code,
fun replaceStudent(key: Int, name: String) {
val old = students[key]
students[key] = Student(old.key, name)
}
modifies students
and is detected as a change.
fun modifyStudent(key: Int, name: String) {
students[key].name = name
}
modifies the name
property of some Student
object which is not seen by the snapshot system as a change.
I recommend you make Student
immutable instead of mutable,
data class Student(val id: Int, val name: String)
Then replaceStudent
would be required to modify update the student.
You could, alternately, change Student
to,
class Student(val id: Int, name: String) {
var name by mutableStateOf(name);
}
which will make Student
observable and notify Compose whenever the name
property is changed.
I recommend making Student
immutable.
As a bonus, I recommend you use SnapshotStateMap
instead of SnapshotStateList
in this case as if you ever call removeStudent
above the key
of the students after the remove will not match the index into the students
. Using a SnapshotStateMap
will fix this. You also need to change the addStudent
to not use size
as the next id
but, rather, use a global integer or an global atomic (if you are multi-threaded) as, now, creating a new student will overwrite an existing student's data as it causes duplicate key
values to be generated if any student was deleted.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论