Android 使用来自 MutableStateFlow<List<MyDataObject>>() 的数据对象字段的值更新 activity

Android update activity with value of data object field from MutableStateFlow<List<MyDataObject>>()

当我更改用于显示下载进度条的对象中的字段值时,我无法可靠地从 viewModel() 更新我的 activity/UI 图层。 activity 观察到对象在列表中的添加和删除正常,但没有更改进度字段。

数据Class

data class DownloadObject(
   val id: String?,
   var progress: Float,
)

视图模型

class MyViewModel () : ViewModel() {

   private val _progressList = MutableStateFlow<List<DownloadObject>>(emptyList())
   val progressList: StateFlow<List<DownloadObject>>
       get() = _progressList

   //add to list updates the activity
   _progressList.value += DownloadObject

   //remove from list updates the activity
   _progessList.value -= DownloadObject

   // Change progress field doesn't update the activity
   _progressList.value.onEach{
       if(it.id == id) {it.progress = progress}
   }
}

Activity

val progressList by courseViewModel.progressList.collectAsState(emptyList()
...
LinearProgressIndicator(progress = progressList.find { it.id == id }?.progress)

我尝试过使用 mutableStateListOf()MutableLiveData,但遇到了许多相同的问题。我已经参加了 state codelabs 的 compose,但我真的不确定从这里开始做什么。非常感谢任何帮助,谢谢!

// Change progress field doesn't update the activity
   _progressList.value.onEach{
       if(it.id == id) {it.progress = progress}
   }

这实际上不会在您的 progressList StateFlow 中触发更新。 要做到这一点,你可能想使用这样的东西:

_progressList.value = progressList.value.map {
    if(it.id == id) {
        it.copy(progress = progress)
    } else {
        it
    }
}

添加和删除您的列表实际上是在更新 UI,因为您正在使用“+”和“-”运算符执行这些操作,这些运算符会在后台创建一个新列表。因此,如果您想更新列表的内容,然后重新组合,您要么必须做类似的事情,要么改变您的方法。

第一个选项,你可以

_progressList.value = progressList.value.onEach{ // Or something of equivalent sort, if Kotlin is smart enough
       if(it.id == id) {it.progress = progress}
   }

更好的方法是在使用 compose 时始终使用 MutableState 而不是 Flow 或其他方法。它是死的干净。

class MyViewModel () : ViewModel() {

   val progressList = mutableStateListOf<DownloadObject>()

    /* Treat it as a regular list object now*/

   _progressList += DownloadObject

   _progessList.value -= DownloadObject

    // It hopefully will work now
   _progressList.forEach{
       if(it.id == id) {it.progress = progress}
   }
}

Activity:-

val progressList by courseViewModel.progressList // That's it
...
LinearProgressIndicator(progress = progressList.find { it.id == id }?.progress)

看看它是否有效并告诉我