[英]How to update UI in coroutines in Kotlin 1.3
我正在尝试调用 API,当我的变量准备好时,分别更新 UI 组件。
这是我正在启动协程的网络单身人士:
object MapNetwork {
fun getRoute(request: RoutesRequest,
success: ((response: RoutesResponse) -> Unit)?,
fail: ((throwable: Throwable) -> Unit)? = null) {
val call = ApiClient.getInterface().getRoute(request.getURL())
GlobalScope.launch(Dispatchers.Default, CoroutineStart.DEFAULT, null, {
try {
success?.invoke(call.await())
} catch (t: Throwable) {
fail?.invoke(t)
}
})
}
}
这就是我所说的:
network.getRoute(request,
success = {
// Make Some UI updates
},
fail = {
// handle the exception
})
而且我收到异常,表示无法从 UI 线程以外的任何线程更新 UI:
com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread
我已经尝试过这个解决方案,但自 Kotlin 1.3 起, Continuation<T>
类中的resume
已“弃用”
要回答您的直接问题,您必须简单地在正确的上下文中启动协程:
val call = ApiClient.getInterface().getRoute(request.getURL())
GlobalScope.launch(Dispatchers.Main) {
try {
success?.invoke(call.await())
} catch (t: Throwable) {
fail?.invoke(t)
}
}
但是,这只是冰山一角,因为您的方法是使用协程的错误方法。 它们的主要好处是避免回调,但您正在重新引入它们。 您还通过使用非生产用途的GlobalScope
侵犯了结构化并发最佳实践。
显然,您已经有了一个异步 API,它为您提供了一个可以await
的Deferred<RoutesResponse>
。 使用方法如下:
scope.launch {
val resp = ApiClient.getInterface().getRoute(request.getURL()).await()
updateGui(resp)
}
您可能会因为我建议在每个 GUI 回调中都有一个launch
块而感到苦恼,您必须在其中执行可挂起的代码,但这实际上是使用此功能的推荐方式。 它与编写Thread { ... my code ... }.start()
严格并行,因为launch
块的内容将与其外部的代码同时运行。
上面的语法假设你已经准备好一个实现CoroutineScope
的scope
变量。 例如,它可以是您的Activity
:
class MyActivity : AppCompatActivity(), CoroutineScope by MainScope {
override fun onDestroy() {
super.onDestroy()
cancel()
}
}
MainScope
委托将默认协程调度程序设置为Dispatchers.Main
。 这允许您使用普通的launch { ... }
语法。
private var viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
uiScope.launch {
withContext(Dispatchers.IO) {
//Do background tasks...
withContext(Dispatchers.Main){
//Update UI
}
}
}
如果你使用 coroutines-android 你可以使用Dispatchers.Main
(gradle 依赖是implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
)
network.getRoute(request,
success = {
withContext(Dispatchers.Main) {
// update UI here
}
},
fail = {
// handle the exception
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.