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

Posted

技术标签:

【中文标题】Android 使用来自 MutableStateFlow<List<MyDataObject>>() 的数据对象字段的值更新活动【英文标题】:Android update activity with value of data object field from MutableStateFlow<List<MyDataObject>>() 【发布时间】:2021-10-17 05:21:39 【问题描述】:

当我更改用于显示下载进度条的对象中的字段值时,我无法可靠地从viewModel() 更新我的活动/UI 层。该活动可以很好地观察列表中对象的添加和删除,但不会更改进度字段。

数据类

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
   

活动

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

我尝试过使用mutableStateListOf()MutableLiveData,但遇到了许多相同的问题。我已经将两个州代码实验室都用于撰写,但我真的不知道从这里做什么。非常感谢任何帮助,谢谢!

【问题讨论】:

如果您希望您的问题得到解答,您需要让专家尽快获得具有可重现问题的工作样本。完美地,我应该将您的代码粘贴到我的示例项目中,并在我运行它时尽快看到问题。在您的情况下,我不知道您如何存储/更改 id 以及为什么 find 可能不会以任何原因返回 null 【参考方案1】:
// 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
    

【讨论】:

【参考方案2】:

在列表中添加和删除实际上是在更新 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
   

活动:-

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

看看它是否有效并告诉我

【讨论】:

谢谢,虽然这确实更新了列表的内容,但它不会触发活动可观察到的状态更新。 哪个不会触发重组?第一种还是第二种方法? 这些方法都不会触发活动中的重组。这不是我向活动公开的变量类型的问题(mutableStateOf、mutableStateListOf、flow、MutableLiveData 等),因为我都试过了。我标记为正确的答案,映射然后复制条件,确实有效!

以上是关于Android 使用来自 MutableStateFlow<List<MyDataObject>>() 的数据对象字段的值更新活动的主要内容,如果未能解决你的问题,请参考以下文章

使用 servlet/jsp 检查 HTTP 请求是不是来自 Android 手机

在 Android 上使用来自 libGDX 的 SQLite

使用来自 android 的 google/gtalk 帐户

可变状态 VS 可变状态流?

手动观察 SnapshotStateList

在 Android 上播放来自 Internet 的视频时使用啥格式?