我正在尝试使用异步更新适配器内的列表,我可以看到有太多样板。
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 模式是:
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
。
注意:使用 job.await()
而不是 job.join()
因为 await()
重新抛出异常,但 join()
不会。如果您使用 join()
,则需要在作业完成后检查 job.isCompletedExceptionally
。
要启动 并发 改造调用,您可以这样做:
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(); };
https://stackoverflow.com/questions/43132080/