Moh*_*sen 12 android ui-thread kotlin kotlin-coroutines
我正在尝试调用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)
}
})
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我所说的:
network.getRoute(request,
success = {
// Make Some UI updates
},
fail = {
// handle the exception
})
Run Code Online (Sandbox Code Playgroud)
我得到的异常表示无法从UI线程以外的任何线程更新UI:
com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread
Run Code Online (Sandbox Code Playgroud)
我已经尝试过这个解决方案,但是从Kotlin 1.3开始resume,Continuation<T>课堂上已经"弃用"了
X-B*_*... 12
private var viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
uiScope.launch {
withContext(Dispatchers.IO) {
//Do background tasks...
withContext(Dispatchers.Main){
//Update UI
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*nik 10
要回答您的直接问题,您必须在正确的上下文中启动协程:
val call = ApiClient.getInterface().getRoute(request.getURL())
GlobalScope.launch(Dispatchers.Main) {
try {
success?.invoke(call.await())
} catch (t: Throwable) {
fail?.invoke(t)
}
}
Run Code Online (Sandbox Code Playgroud)
然而,这只是冰山一角,因为你的方法是使用协同程序的错误方法.他们的主要好处是避免回调,但你正在重新引入它们.您还通过使用不适合生产用途的结构化并发最佳实践来侵犯您GlobalScope.
显然,你已经有了一个异步API,让你一个Deferred<RoutesResponse>,你可以await上.使用方法如下:
scope.launch {
val resp = ApiClient.getInterface().getRoute(request.getURL()).await()
updateGui(resp)
}
Run Code Online (Sandbox Code Playgroud)
您可能会因为我建议launch在每个GUI回调中都有一个块来执行可挂起的代码而感到苦恼,但实际上这是使用此功能的推荐方法.它与写入严格并行,Thread { ... my code ... }.start()因为launch块的内容将同时运行到它之外的代码.
上面的语法假设您有一个scope实现的变量ready CoroutineScope.例如,它可以是你的Activity:
class MyActivity : AppCompatActivity(), CoroutineScope {
lateinit var masterJob: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + masterJob
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
masterJob = Job()
}
override fun onDestroy() {
super.onDestroy()
masterJob.cancel()
}
}
Run Code Online (Sandbox Code Playgroud)
请注意如何coroutineContext设置默认协程调度程序Dispatchers.Main.这允许您使用普通launch { ... }语法.
如果你正在使用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
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5677 次 |
| 最近记录: |