2

所以我正在将一个示例应用程序从 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's 片段或活动方法中简单地取消订阅并清除CompositeSubscription对象。但是我想知道asReference()Anko Coroutines 中的函数是否也一样,并且不需要保存列表Deferred<T>然后对其进行迭代并一一取消。

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

更新

 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()onDestroy()要使其正常工作,我必须检查作业是否处于活动状态,并将其转换为 if/else 和返回或不返回数据。取消工作后有没有更好的方法来退货?

4

1 回答 1

1

正如您在asReference()源代码中看到的那样,它只不过是一个弱引用和调用方法来获取CancellationException在收集对象时抛出的引用。它不会做任何事情来取消操作。只是知道收集的对象

因此您需要保留Job或其子类型的引用以取消操作。

launch来自kotlinx.coroutines的协程构建器返回一个 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-要在子协程中取消,您必须创建父/子作业层次结构。我将 parent( launch)Job引用传递给子协程(async) 来实现这一点。

3- 因为取消是合作取消的实现,所以必须异步完成(见这里的例子)。

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

于 2018-03-29T13:16:12.133 回答