[英]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.