【发布时间】:2021-06-13 12:21:35
【问题描述】:
val scope = CoroutineScope(
Job() + Dispatchers.Main
)
scope.launch {
beforeExecute()
val result = withContext(dispatcher) { doInBackground(*params) }
if (!isCancelled) {
postExecute(result)
} else {
cancelled(result)
}
status = Status.FINISHED
}
scope.cancel()
如果我将scope.cancel() 放在启动之外,它会立即取消协同程序而不调用启动块代码。这是预期的吗?为什么会发生?如果我希望协同程序在完成后结束,应该将取消放在启动块末尾的启动内在启动内执行代码?
更新
根据 Hau Luu 的回答和 Marko Topolnik 的评论,
”在启动结束时,我认为任务已经完成,你不需要 手动取消协程。”
和
“一旦你的任务完成,协程就会从内存中消失。”
但是在案例 2 中,如果我启动另一个启动,除非我们像案例 1 一样取消第一次启动中的协程,否则它会被执行。 那么是否可以确定在任务完成后协程会在我们手动调用 cancel() 的情况下从内存中消失?Bcoz 编译器永远不会知道要执行的最后一次启动是什么,之后它需要结束协程
案例 1
scope.launch {
Log.e("Task","1");
scope.cancel()
}
scope.launch {
Log.e("Task","2");
}
仅打印任务 1
案例 2
scope.launch {
Log.e("Task","1");
}
scope.launch {
Log.e("Task","2");
}
打印任务 1 和 2
【问题讨论】:
-
除非执行此协程的对象已被处置且其结果不再相关,否则不应取消范围。如果您在发布启动块后立即取消范围,您期望会发生什么?
-
@Pawel 我希望一旦我的任务完成,协程应该停止运行。协程的 AFAIK 生命周期取决于我们使用的范围,如果我使用像 viewmodelscope 这样的内置范围,那么 lifecyale 与生命周期相关联viewmodel 的。但是我在这里使用自定义 CoroutineScope。如何确保协程在我的任务完成后不会保留在内存中?我在抽象类 final 方法中使用此代码,我的任务在
status = Status.FINISHED行之后完成。 -
正如您所说,viewmodelscope 与 viewmodel 的生命周期相关联,因此您应该将范围与类的生命周期联系起来。声明一个协程执行的范围是没有意义的。如果它是静态方法,那么您不妨将其发布在
GlobalScope上,因为协程一旦执行完毕就不会留在内存中。 -
@Pawel 我相信 GlobalScope 与应用程序的生命周期有关,不应使用!
-
@AndroidDeveloper 是的!理论上,它应该是。但由于我无法检查 CS (CoroutineScope) 的存在,所以我无法确认。因为作用域内协程的生命周期可能比启动它的方法的生命周期长。
标签: android kotlin kotlin-coroutines