android - 迭代协程并等待结果
问题描述
我有一种情况,我需要调度仅在运行时才知道的不确定数量的网络调用。每个调用都会返回一个列表。当每个都返回时,我需要将这些列表合并到一个合并列表中。我正在使用协程来做到这一点。
我遇到的问题与我不知道应用程序需要进行多少网络调用有关。为了解决这个问题,我使用循环在运行时迭代调用列表:
private suspend fun fetchData(params: List<Interval>): List<Item> {
val smallLists = mutableListOf<Deferred<List<Item>>>()
val merged = mutableListOf<List<Item>>()
for (index in 0 until params.size) {
val param = params[index]
// loop stop iterating after this call is dispatched
smallLists[index] = CoroutineScope(Dispatchers.IO).async {
fetchList(param)
}
}
for (index in 0 until smallLists.size) {
merged[index] = smallLists[index].await()
}
return merged.flatMap { it.toList() }
}
private fun fetchList(param: Interval) : List<Item> {
return dataSource.fetchData(param)
}
这段代码发生的事情是它进入了第一个循环。params
清单是正确的。它分派第一个查询,然后这个查询返回(我可以通过 Charles 代理看到这个)。
但这就是一切都死去的地方。应用程序对网络响应不做任何事情,循环终止(即没有第二次循环迭代)。
我知道其他一切都完好无损,因为我有一个不包括循环的替代版本。它只执行两个查询,等待它们的结果,然后返回组合列表。它工作正常,除了它不会处理动态运行时情况:
private suspend fun fetchData(params: List<Interval>): List<Item> {
val list1 = CoroutineScope(Dispatchers.IO).async {
fetchList(params[0])
}
val list2 = CoroutineScope(Dispatchers.IO).async {
fetchList(params[1])
}
return list1.await() + list2.await()
}
这里可能是一个简单的解决方案,但我没有看到。任何帮助表示赞赏。
解决方案
这是不正确的:
smallLists[index] = CoroutineScope(Dispatchers.IO).async {
fetchList(param)
}
你smallLists
是空的,所以你不能访问 index index
。改成这样
smallLists.add(CoroutineScope(Dispatchers.IO).async {
fetchList(param)
}
)
请注意,您也可以调用awaitAll()
您的 s 列表async
,以简化您的代码:
private suspend fun fetchData(params: List<Interval>): List<Item> {
val smallLists = mutableListOf<Deferred<List<Item>>>()
for (index in 0 until params.size) {
val param = params[index]
// loop stop iterating after this call is dispatched
smallLists.add(CoroutineScope(Dispatchers.IO).async {
fetchList(param)
}
})
val merged = smallLists.awaitAll()
return merged.flatMap { it.toList() }
}
推荐阅读
- sql - 如何用相同 PolicyNumber 的非空值替换空字符串
- javascript - AngularJS单击时突出显示锚标记
- html - Bootstrap 4:高度相等的 div,中间有颜色填充和装订线
- mysql - 使用 VARCHAR 作为 ID 的任何数据库问题
- c++ - 可以将 C++ 复制构造函数用于其他目的吗?
- mp3 - 如何在网站上自动播放 Mp3
- android - Kotlin - AlertDialog 中的中心消息
- python - 无法在 Anaconda 的虚拟环境中安装 Spyder
- c++ - Boost::beast:多个 async_write 调用正在触发一个断言错误
- ember.js - 如何在 Ember 中导入 ZeroEx npm 模块