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
私はすでに this ソリューションを試しましたが、Continuation<T>
クラスのresume
はKotlin 1.3以降「非推奨」です
直接の質問に答えるには、正しいコンテキストでコルーチンを起動する必要があります。
_val call = ApiClient.getInterface().getRoute(request.getURL())
GlobalScope.launch(Dispatchers.Main) {
try {
success?.invoke(call.await())
} catch (t: Throwable) {
fail?.invoke(t)
}
}
_
ただし、コルーチンを使用する方法は間違っているため、これは氷山の一角にすぎません。彼らの主な利点はコールバックを回避することですが、あなたはそれらを再紹介しています。また、 構造化された並行性 のベストプラクティスを侵害しています。これは、本番用ではないGlobalScope
を使用して。
await
onできる_Deferred<RoutesResponse>
_を提供する非同期APIを既に持っているようです。使用方法は次のとおりです。
_scope.launch {
val resp = ApiClient.getInterface().getRoute(request.getURL()).await()
updateGui(resp)
}
_
中断可能なコードを実行する必要があるすべてのGUIコールバックでlaunch
ブロックを使用することを提案しているという事実に悩まされるかもしれませんが、実際にはこの機能を使用する推奨方法です。 launch
ブロックのコンテンツは、その外部のコードと同時に実行されるため、Thread { ... my code ... }.start()
の記述と厳密に並行しています。
上記の構文は、scope
を実装する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()
}
}
_
coroutineContext
がデフォルトのコルーチンディスパッチャーを_Dispatchers.Main
_に設定する方法に注意してください。これにより、プレーンな_launch { ... }
_構文を使用できます。
コルーチン-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
})