[英]How to update a TextView after an API response with Kotlin coroutines?
[英]Calling multiple API requests and waiting for response using Kotlin Coroutines
应用了代码更改。
我遵循了有关如何创建 kotlin 协程和执行网络请求的指南,最终得到:
suspend fun <T : Any> safeApiCall(call: suspend () -> Response<T>): ApiResult<T> {
return safeApiResult(call)
}
private suspend fun <T: Any> safeApiResult(call: suspend ()-> Response<T>) : ApiResult<T>{
val response = call.invoke()
return if (response.isSuccessful) {
val body = response.body()
if (body == null) {
ApiResult.Error(response.code())
} else {
ApiResult.Success(body)
}
} else {
ApiResult.Error(response.code())
}
}
suspend fun getSnappedPoints(path: String): ApiResult<SnappedPointsData> {
return safeApiCall(
call = { googleRoadsService.getSnappedPoints(path).await()}
)
}
并调用网络请求如下所示:
private fun getSnappedPoints() {
val paths = Utils.getPathFromLocations(locations)
CoroutineScope(Dispatchers.IO).launch {
val results = paths.map {
async { googleRoadsRepository.getSnappedPoints(it) }
}.awaitAll()
Timber.i("results: ${results.size}")
val snappedPoints = ArrayList<LocationSnap>()
results.forEach {
if (it is ApiResult.Success) {
snappedPoints.addAll(it.data.snappedPoints)
}
}
withContext(Dispatchers.Main) {
if (snappedPoints.isNotEmpty()) {
drawPolyline(snappedPoints)
} else {
showError()
}
}
}
}
当前问题:
当我单击特定项目时调用函数getSnappedPoints()
。 它第一次实际调用 google API 并且结果 > 0(大小),但是如果我返回并在同一/其他项目getSnappedPoints()
二次单击,则调用getSnappedPoints()
, paths
不是 Empty,但不知何故它确实如此不调用googleRoadsRepository.getSnappedPoints(it)
并且有点跳过调试中的那一步,我能看到的只是结果始终为 0。什么可能导致这种情况?
每个协程( launch
)都是一个并发单元,如果你想并发运行每个请求,你必须为每个并发请求做一个launch
/ async
。
private fun getPoints() {
val multipleParams = Utils.getArrayListOfParams()
coroutineJob = CoroutineScope(Dispatchers.IO).launch {
val results = multipleParams.map {
async { Repository.getPoints(it) }
}.awaitAll()
// Do something with results, once all have been gotten.
// result and result2, result[it] has finished, continue)
}
}
奖金:
CoroutineScope
而不取消它,那么您应该使用GlobalScope
作为优化。 (像这样GlobalScope.launch(Dispatchers.IO)
)Dispatchers.IO
来执行此操作,因为您似乎没有阻塞协程/线程。 Dispatchers.Default
会做得很好。coroutineJob
变量的目的,但它看起来很可疑。当您在 IO 线程时,使用async + await
的必要性是什么? 在 IO 范围内,您可以自由挂起并等待响应。
试试这个并通知我知道结果会怎样?
private fun getSnappedPoints() {
val paths = Utils.getPathFromLocations(locations)
CoroutineScope(Dispatchers.IO).launch {
val results = paths.map {
googleRoadsRepository.getSnappedPoints(it)
}
// rest of you code...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.