android - Anko协程扩展的正确使用方法是什么?

标签 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基类有一个 CompositeSubscriptiononDestroy的 fragment 或 Activity 方法简单取消订阅并清除 CompositeSubscription目的。但我想知道 asReference() 是否Anko Coroutines 的函数做同样的事情,不需要保存 Deferred<T> 的列表。然后迭代它并一个一个地取消。

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

更新

 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()方法,但要使其工作,我必须检查作业是否处于 Activity 状态,并将其转换为 if/else 和返回或不返回数据。有什么更好的方法可以在工作取消后返回吗?

最佳答案

正如您在 asReference() 中看到的那样source 它只不过是一个弱引用和调用方法来获取在收集对象时抛出 CancellationException 的引用。它不执行任何取消操作。只是意识到收集到的对象

所以你需要保留一个 Job 的引用或其子类型以取消操作。

launch 来自 kotlinx.coroutines 的协程构建器返回一个作业实例。这是一个例子:

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- 因为取消是合作的取消实现必须在异步中完成(参见示例 here)。

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

关于android - Anko协程扩展的正确使用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47461766/

相关文章:

android - ADT Eclipse + Gradle +依赖项

kotlin - 使用 Kotlin Channel 是什么意思?

kotlin 协程。启动{乐趣}和启动{暂停乐趣}之间的区别

kotlin - Delay()准确性问题/作业调度程序的异常行为

java - 在两个以上的 fragment 之间传递数据

android - 在此类中实现异步任务时出错

java - 相机目录为空

android - IntentService (kotlin) 的默认构造函数

android - 无法使用数据绑定(bind) Android 从 ViewModel 与 XML 通信

spring-boot - 在intellij中运行并执行jar时的微妙差异