使用Anko Coroutines扩展的正确方法是什么?

时间:2017-11-23 18:44:04

标签: android kotlin kotlinx.coroutines anko

所以我正在将一个示例应用程序从RxJava迁移到Kotlin / Anko Corountines,我想知道我是否正在做最好的(第一个)方法:

fun getPopulationList() {
    val ref = asReference()

    async(UI) {
        try {
            ref().setCurrentState(ViewState.State.LOADING)
            val background = bg {
                repository.populationResponse().execute().body()
            }

            ref().let {
                it.response = background.await()
                it.mvpView?.onGetData(it.response)
                it.setCurrentState(ViewState.State.FINISH)
            }
        } catch (e: Exception) {
            e.printStackTrace()
            ref().mvpView?.onError(e)
        }
    }
}

我正在使用MVP架构,我的Presenter基类有一个CompositeSubscription,在onDestroy的片段或活动方法中,只需取消订阅并清除{{1对象。但是我想知道Anko Coroutines的CompositeSubscription函数是否也这样做,并且不需要保存asReference()列表然后迭代它并逐个取消。

顺便说一句,如果我添加一个Deferred<T>来模拟一个大事务并销毁片段,我可以在logcat中看到HTTP响应,即使片段不可见/被破坏,而RxJava也不会发生,所以我认为我没有正确使用。

更新

Thread.sleep(5000)

我可以在 fun getPopulationList() { val ref = asReference() job = launch(UI) { try { ref().setCurrentState(ViewState.LOADING) val background = bg { Thread.sleep(5000) //simulate heavy IO if (isActive) { repository.populationResponse().execute().body() } else { return@bg null } } ref().let { it.response = background.await() it.mvpView?.onGetData(it.response) it.setCurrentState(ViewState.FINISH) } } catch (e: Exception) { RestHttpExceptionHandler().handle(UI, e, ref()) } } } 方法中调用job.cancel()时取消协程,但要使其正常工作,我必须检查作业是否处于活动状态,并转换为if / else和a是否返回数据。当工作被取消时,还有更好的方法可以退货吗?

1 个答案:

答案 0 :(得分:1)

正如您在asReference()源中所看到的,只有弱引用和调用方法才能获取在收集对象时抛出CancellationException的引用。取消操作没有任何作用。只是意识到收集的对象

所以你需要继续引用它的Job或子类型来取消操作。

来自kotlinx.coroutines

launch协程构建器返回一个Job实例。这是一个例子:

private lateinit var job: Job

private fun startCoroutines() {
    val ref = asReference()
    job = launch(UI) {
        try {
            val deferred = async(parent = coroutineContext[Job]) {
                    //do some work
                    result//return
            }

            ref().setData(deferred.await())
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

}


override fun onDestroy() {
    super.onDestroy()
    job.cancel()
}

注意:

1-当结果类型不重要时launch可以代替async使用。

2-在子协程中取消您必须创建父/子作业层次结构。我将父(launchJob引用传递给子协程(async)以实现此目的。

3- 取消是合作的 取消实施必须在异步中完成(参见示例here)。

3- job.cancel()用于onDestroy取消作业及其子异步。这可以在Presenter中以MVP模式完成。