问题描述
因此,我正在将一个示例应用程序从RxJava迁移到Kotlin/Anko Corountines,我想知道我是否正在使用它的最佳方法(第一种):
So I am migrating an example app from RxJava to Kotlin/Anko Corountines and I am wondering if I am doing the best (first) approach of it:
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
的片段或活动方法中,简单地取消预订并清除CompositeSubscription
对象.但是我想知道Anko Coroutines的asReference()
函数是否也是如此,并且没有必要保存Deferred<T>
的列表,然后对其进行迭代并逐个取消.
I am using an MVP architecture where my Presenter
base class had a CompositeSubscription
and in the onDestroy
's fragment or activity method simple unsubscribe and clear the CompositeSubscription
object. But i am wondering if the asReference()
function from Anko Coroutines does the same and there is no need to save a list of Deferred<T>
and then iterate it and cancel one by one.
如果我添加Thread.sleep(5000)
来模拟大事务并破坏片段,即使在片段不可见/使用RxJava销毁该片段的情况下,我也能在logcat中看到HTTP响应,所以我想我使用不正确.
BTW if I add a Thread.sleep(5000)
to simulate a big transaction and destroy the Fragment I can see in the logcat the HTTP response even after the fragment is not visible/destroyed while with RxJava doesn't happen, so I think I am not using properly.
更新
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())
}
}
}
我可以在onDestroy()
方法中调用job.cancel()
时取消协程,但要使其正常工作,我必须检查该作业是否处于活动状态,并转换为if/else并返回或不返回数据.取消工作后,还有什么更好的退货方法吗?
I am able to cancel the coroutine while calling job.cancel()
in onDestroy()
method but to make it work I have to check if the job is active or not and that translate into an if/else and a return or not data. Is there any better way to return something when the job was cancelled?
推荐答案
您可以在 asReference()来源,除了弱引用和调用方法之外,其他方法无非就是获取收集对象时抛出CancellationException
的引用.它不会做任何取消操作的事情.只是意识到收集到的物体.
As you can see in asReference() source it is nothing other than a weak reference and invoke method to get reference that throws CancellationException
when object is collected. it does not do anything to cancel operation. just is aware of collected object.
所以您需要保留作业或它的子类型以取消操作.
so you need to keep reference of a Job or subtype of it to cancel operation.
launch
协程生成器返回一个Job实例.这是一个例子:
launch
coroutine builder from kotlinx.coroutines returns a Job instance. here is an example:
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
.
1- when result type is not important launch
can be used instead of async
.
2-要取消子协程,必须创建父/子作业层次结构.我通过对子协程(async)的parent(launch
)Job
引用来实现此目的.
2- to do cancellation in child coroutines you must create parent/child job hierarchies. I passed parent(launch
) Job
reference to child coroutine(async) to achieve this.
3-因为 取消是合作 ,取消实施必须以异步方式完成(请参见示例此处).
3- job.cancel()
用于onDestroy取消作业,它是子异步对象.这可以在Presenter中以MVP模式完成.
3- job.cancel()
is used in onDestroy cancels job and it's child async. this can be done in Presenter in MVP pattern.
这篇关于使用Anko Coroutines扩展程序的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!