MutableStateFlow无法与MutableList一起使用

4

这是我尝试使用的可变状态流(MutableStateFlow)值:

val songList: MutableStateFlow<MutableList<Song>> = MutableStateFlow(arrayListOf())

我需要观察我的 MutableList 在执行 add、removeAt 等方法后的变化,但无法实现。我猜想是因为列表只有元素发生了改变而不是列表本身,所以 collect 方法没有被触发。

如果可能,我该如何使用 StateFlow 实现这一点?如果不行,正确的做法是什么?

请注意,我需要 arrayListOf() 的初始值,所以 LiveData 可能对我来说不够用。

3个回答

3

在你的视图模型中:

val songList: MutableStateFlow<MutableList<Song>> = MutableStateFlow(emptyList()) // modified

fun add(song: Song) {
    songList.update {
        songList.value.toMutableList().apply { this.add(song) }
    }
}

在可组合中:

val songs = yourViewModel.songList.collectAsStateWithLifecycle()

声明类型为只读列表会很好,这样可以避免意外改变列表而不是复制它。 val songList: MutableStateFlow<List<Song>> = ... - undefined

1

要更新 Stateflow 内部的 MutableList,您需要根据以下条件进行映射项,我已经完成了这个过程,并且它表现良好。

 _userList.value = _userList.value.map {
                if (it?.userName == updatedUser.userName) updatedUser
                else it
            }

这里的_userList是一个MutableStateFlow。@Sam Sen的解释在我的解决方案中帮了我很多。


1
  • 有用的阅读材料: 当嵌套属性发生更改时通知LiveData观察者

  • 问题是什么:

    • 如果嵌套字段被更改,StateFlow和LiveData将不会收到通知。

    • 示例1: 更新列表中的特定项目(不是添加/删除)。

    • 示例2: 更新对象的特定属性。


解决方法:

  1. Create helper extension function:

    fun <T> List<T>.mapButReplace(targetItem: T, newItem: T) = map {
        if (it == targetItem) {
            newItem
        } else {
            it
        }
    }
    
  2. React on action (ex: click event):

     val newStudent = student.copy(isSelected = !student.isSelected)
    
     viewModel.updateStudents(student, newStudent)
    
  3. Handle in ViewModel:

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

谢谢您的回答。所以,对我来说,当观察列表项时似乎没有直接的方法。 - bugra
@bugra Compose已经解决了这个问题:https://dev59.com/3lEG5IYBdhLWcg3wXbY2#67252955。 - Sam Chen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接