Kotlin 协程在 Android 中的正确方式
我正在尝试使用异步更新适配器内的列表,我可以看到样板太多.
I'm trying to update a list inside the adapter using async, I can see there is too much boilerplate.
这是使用 Kotlin 协程的正确方法吗?
Is it the right way to use Kotlin Coroutines?
可以进一步优化吗?
fun loadListOfMediaInAsync() = async(CommonPool) {
try {
//Long running task
adapter.listOfMediaItems.addAll(resources.getAllTracks())
runOnUiThread {
adapter.notifyDataSetChanged()
progress.dismiss()
}
} catch (e: Exception) {
e.printStackTrace()
runOnUiThread {progress.dismiss()}
} catch (o: OutOfMemoryError) {
o.printStackTrace()
runOnUiThread {progress.dismiss()}
}
}
在这个问题上挣扎了好几天后,我认为使用 Kotlin 的 Android Activity 最简单明了的 async-await 模式是:
After struggling with this question for days, I think the most simple and clear async-await pattern for Android activities using Kotlin is:
override fun onCreate(savedInstanceState: Bundle?) {
//...
loadDataAsync(); //"Fire-and-forget"
}
fun loadDataAsync() = async(UI) {
try {
//Turn on busy indicator.
val job = async(CommonPool) {
//We're on a background thread here.
//Execute blocking calls, such as retrofit call.execute().body() + caching.
}
job.await();
//We're back on the main thread here.
//Update UI controls such as RecyclerView adapter data.
}
catch (e: Exception) {
}
finally {
//Turn off busy indicator.
}
}
协程的唯一 Gradle 依赖项是:kotlin-stdlib-jre7
、kotlinx-coroutines-android
.
The only Gradle dependencies for coroutines are: kotlin-stdlib-jre7
, kotlinx-coroutines-android
.
注意:使用 job.await()
而不是 job.join()
因为 await()
重新抛出异常,但 join()
不会.如果您使用 join()
,您将需要在作业完成后检查 job.isCompletedExceptionally
.
Note: Use job.await()
instead of job.join()
because await()
rethrows exceptions, but join()
does not. If you use join()
you will need to check job.isCompletedExceptionally
after the job completes.
要开始并发改造调用,您可以这样做:
To start concurrent retrofit calls, you can do this:
val jobA = async(CommonPool) { /* Blocking call A */ };
val jobB = async(CommonPool) { /* Blocking call B */ };
jobA.await();
jobB.await();
或者:
val jobs = arrayListOf<Deferred<Unit>>();
jobs += async(CommonPool) { /* Blocking call A */ };
jobs += async(CommonPool) { /* Blocking call B */ };
jobs.forEach { it.await(); };