我有一个情况,我需要仅在运行时派遣不确定的网络调用数量。每个呼叫都返回列表。返回时,我需要将这些列表组合到一个合并列表中。我正在使用Coroutines来做到这一点。
我遇到的问题与我不知道该应用程序需要进行多少网络调用的事实有关。为了解决这个问题,我正在使用一个循环在运行时迭代通话列表:
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
。像这样更改它
smallLists.add(CoroutineScope(Dispatchers.IO).async {
fetchList(param)
}
)
请注意,您也可以在async
s列表中调用awaitAll()
,以简化您的代码:
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() }
}