Kotlin Coroutines是Android的正确方法

我正在尝试使用异步更新适配器内的列表,我可以看到有太多的样板。

这是使用Kotlin协同程序的正确方法吗?

这可以优化更多?

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活动最简单明了的异步模式是:

 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-jre7kotlinx-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(); }; 

我想你可以通过使用Android应用程序的UI上下文而不是CommonPool来摆脱runOnUiThread { ... }

UI上下文由kotlinx-coroutines-android模块提供。

就像sdeff所说的,如果你使用UI上下文,默认情况下,该协程中的代码将在UI线程上运行。 而且,如果您需要在另一个线程上运行指令,则可以使用run(CommonPool) {}

此外,如果您不需要从方法中不返回任何内容,则可以使用函数launch(UI)而不是async(UI) (前者将返回Job ,后者将返回Deferred<Unit> )。

一个例子可能是:

 fun loadListOfMediaInAsync() = launch(UI) { try { run(CommonPool) { //The coroutine is suspended until run() ends adapter.listOfMediaItems.addAll(resources.getAllTracks()) } adapter.notifyDataSetChanged() } catch(e: Exception) { e.printStackTrace() } catch(o: OutOfMemoryError) { o.printStackTrace() } finally { progress.dismiss() } } 

如果您需要更多的帮助,我建议您阅读kotlinx.coroutines的主要指南 ,此外, 协程+ UI的指南