Así que estoy actualizando mi RecylerView con StateFlow<List> como sigue:
Mi clase de datos:
data class Student(val name: String, var isSelected: Boolean)Mi lógica ViewModel:
fun updateStudentsOnSelectionChanged(targetStudent: Student) { val targetIndex = _students.value.indexOf(targetStudent) val isSelected = !targetStudent.isSelected _students.value[targetIndex].isSelected = isSelected //<- doesn't work } Problema: la interfaz de usuario no cambia, pero isSelected dentro _student cambia, ¿qué está pasando? (igual que LiveData )
Supongo que _students es StateFlow<List> . Cambiar la propiedad isSelected del modelo Student no StateFlow . La solución sería hacer que la propiedad isSelected de la clase de datos Student sea inmutable para compararla cuando se establece un nuevo estado, crear una MutableList a partir de la lista actual y copiar el objeto Student existente con el nuevo valor para la propiedad isSelected :
data class Student(val name: String, val isSelected: Boolean) val students = _students.value.toMutableList() students[targetIndex] = students[targetIndex].copy(isSelected = isSelected) _students.value = studentsOk, gracias a @Tenfour04 y @Sergey, finalmente descubrí que StateFlow/LiveData no puede detectar los cambios internos, eso es porque ambos están comparando la Referencia del .value .
Eso significa que si quiero forzar la actualización de StateFow<List> , la única forma es asignarle una nueva List , por lo tanto, creé la siguiente función de extensión auxiliar:
fun <T> List<T>.mapButReplace(targetItem: T, newItem: T) = map { if (it == targetItem) { newItem } else { it } } //this function returns a new List with the content I wanted En Fragment :
val itemCheckAction: (Student) -> Unit = { student -> val newStudent = student.copy(isSelected = !student.isSelected) //prepare a new Student viewModel.updateStudentsOnSelectionChanged(student, newStudent) //update the StateFlow } En ViewModel :
fun updateStudentsOnSelectionChanged(currentStudent: Student, newStudent: Student) { val newList = _students.value.mapButReplace(currentStudent, newStudent) _students.value = newList //assign a new List with different reference }