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?
The snapshot system will detect changes in
SnapshotStateListitself, not in changes to mutable state within it.The code,
modifies
studentsand is detected as a change.modifies the
nameproperty of someStudentobject which is not seen by the snapshot system as a change.I recommend you make
Studentimmutable instead of mutable,Then
replaceStudentwould be required to modify update the student.You could, alternately, change
Studentto,which will make
Studentobservable and notify Compose whenever thenameproperty is changed.I recommend making
Studentimmutable.As a bonus, I recommend you use
SnapshotStateMapinstead ofSnapshotStateListin this case as if you ever callremoveStudentabove thekeyof the students after the remove will not match the index into thestudents. Using aSnapshotStateMapwill fix this. You also need to change theaddStudentto not usesizeas the nextidbut, 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 duplicatekeyvalues to be generated if any student was deleted.