所以我正在将一个示例应用程序从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是否返回数据。当工作被取消时,还有更好的方法可以退货吗?
答案 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-在子协程中取消您必须创建父/子作业层次结构。我将父(launch
)Job
引用传递给子协程(async)以实现此目的。
3- 取消是合作的 取消实施必须在异步中完成(参见示例here)。
3- job.cancel()
用于onDestroy取消作业及其子异步。这可以在Presenter中以MVP模式完成。