协程作业即使在从外部函数取消后也能完成
Coroutine job completing even after cancellation from external function
我有这个功能:
suspend fun functionCall(): Job {
return MainScope().launch {
var i = 0
while(i < 3) {
i++
delay(3000)
yield()
}
}
cancel()
}
我在单击按钮时从外部函数调用:
MainScope().launch {
if(functionCall().isActive) {
functionCall().cancelAndJoin()
}
}
这两个函数都在 运行 存储库 class 中。
即使在上面的 if 语句被触发后,它仍在遍历整个 while 循环。我在调试时注意到“i”也被重置为 0,这可能表明该作业被触发了不止一次,但它肯定只被触发了一次,所以我对发生的事情感到困惑。
我想要发生的是在整个作业取消的 if 语句之后,整个函数 return 和 运行 不再有代码。
我也尝试过 while(ensureActive) 并且发生了同样的事情。
我该怎么做?
由于这是 Android,您应该从 lifecycleScope
启动与 UI 相关的协程。如果您的作业需要在屏幕旋转时存活下来,您应该从 viewModelScope
的 ViewModel 内部启动它,并且它不得接触任何 UI 元素。
如果您想在事件发生时取消特定协程,您应该将该协程作业存储在 属性 中,以便您可以在其上调用 cancel()
。因此,例如 Activity 中的典型模式可能是:
private var fooJob: Job? = null
private fun fooSomething() {
fooJob = lifecycleScope.launch {
repeat(5) {
delay(1000)
Log.i("count", it.toString())
}
}
}
private fun cancelCurrentFoo() {
fooJob?.cancel()
}
假设您有一个协程作业,您可以通过调用 ViewModel 的其中一个函数开始,但您希望 Activity/Fragment 能够提前取消它。然后公开一个 return 协程作业的函数:
fun foo() = viewModelScope.launch {
repeat(5) {
delay(1000)
Log.i("count", it.toString())
}
}
Activity 可以调用此函数,它会在 return 中获得一个 Job 实例,它可以随时调用 cancel()
。
我有这个功能:
suspend fun functionCall(): Job {
return MainScope().launch {
var i = 0
while(i < 3) {
i++
delay(3000)
yield()
}
}
cancel()
}
我在单击按钮时从外部函数调用:
MainScope().launch {
if(functionCall().isActive) {
functionCall().cancelAndJoin()
}
}
这两个函数都在 运行 存储库 class 中。 即使在上面的 if 语句被触发后,它仍在遍历整个 while 循环。我在调试时注意到“i”也被重置为 0,这可能表明该作业被触发了不止一次,但它肯定只被触发了一次,所以我对发生的事情感到困惑。
我想要发生的是在整个作业取消的 if 语句之后,整个函数 return 和 运行 不再有代码。
我也尝试过 while(ensureActive) 并且发生了同样的事情。
我该怎么做?
由于这是 Android,您应该从 lifecycleScope
启动与 UI 相关的协程。如果您的作业需要在屏幕旋转时存活下来,您应该从 viewModelScope
的 ViewModel 内部启动它,并且它不得接触任何 UI 元素。
如果您想在事件发生时取消特定协程,您应该将该协程作业存储在 属性 中,以便您可以在其上调用 cancel()
。因此,例如 Activity 中的典型模式可能是:
private var fooJob: Job? = null
private fun fooSomething() {
fooJob = lifecycleScope.launch {
repeat(5) {
delay(1000)
Log.i("count", it.toString())
}
}
}
private fun cancelCurrentFoo() {
fooJob?.cancel()
}
假设您有一个协程作业,您可以通过调用 ViewModel 的其中一个函数开始,但您希望 Activity/Fragment 能够提前取消它。然后公开一个 return 协程作业的函数:
fun foo() = viewModelScope.launch {
repeat(5) {
delay(1000)
Log.i("count", it.toString())
}
}
Activity 可以调用此函数,它会在 return 中获得一个 Job 实例,它可以随时调用 cancel()
。