2

所以我更新我RecylerViewStateFlow<List>如下:

我的数据类:

data class Student(val name: String, var isSelected: Boolean)

我的 ViewModel 逻辑:

fun updateStudentsOnSelectionChanged(targetStudent: Student) {
    val targetIndex = _students.value.indexOf(targetStudent)
    val isSelected = !targetStudent.isSelected

    _students.value[targetIndex].isSelected = isSelected        //<- doesn't work
} 

问题: UI没变,但是isSelected里面_student变了,怎么回事?(与 相同LiveData

4

2 回答 2

0

好的,感谢@Tenfour04 和@Sergey,我终于发现StateFlow/LiveData无法检测到内部更改,那是因为它们实际上都是在比较.value.

这意味着,如果我想强制StateFow<List>更新,唯一的方法是为其分配一个新List的,因此我创建了以下辅助扩展函数:

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

Fragment

val itemCheckAction: (Student) -> Unit = { student ->
    val newStudent = student.copy(isSelected = !student.isSelected)    //prepare a new Student

    viewModel.updateStudentsOnSelectionChanged(student, newStudent)    //update the StateFlow
}

ViewModel

fun updateStudentsOnSelectionChanged(currentStudent: Student, newStudent: Student) {
    val newList = _students.value.mapButReplace(currentStudent, newStudent)

    _students.value = newList       //assign a new List with different reference
}
于 2022-02-21T20:05:02.833 回答
0

我假设_students是一个StateFlow<List>. 更改模型的isSelected属性Student不会触发StateFlow. 解决方法是使数据类的isSelected属性Student不可变,以便在设置新状态时对其进行比较,MutableList从当前列表中创建一个并使用属性Student的新值复制现有对象isSelected

data class Student(val name: String, val isSelected: Boolean)

val students = _students.value.toMutableList()
students[targetIndex] = students[targetIndex].copy(isSelected = isSelected)
_students.value = students
于 2022-02-19T18:09:29.083 回答