作业延迟取消后不会再开始
Job delay is not started again after canceling
所以当我按下一个按钮时,我需要等待 3 秒才能执行另一个方法,我用下面的方法解决了这个问题
val job = CoroutineScope(Dispatchers.Main).launch(Dispatchers.Default, CoroutineStart.DEFAULT) {
delay(THREE_SECONDS)
if (this.isActive)
product?.let { listener?.removeProduct(it) }
}
override fun onRemoveProduct(product: Product) {
job.start()
}
现在,如果我在开始工作后立即按下取消按钮,我就会停止工作,而且工作正常
override fun onClick(v: View?) {
when(v?.id) {
R.id.dismissBtn -> {
job.cancel()
}
}
}
问题是,当我再次执行 onRemoveProduct
执行 job.start()
时,它不会再次启动,似乎 job.isActive
永远不会屈服于 true,为什么会这样?
A Job
一旦取消就无法再次开始。你需要以不同的方式做到这一点。一种方法是每次调用 onRemoveProduct
时创建一个新作业。
private var job: Job? = null
fun onRemoveProduct(product: Product) {
job = scope.launch {
delay(THREE_SECONDS)
listener?.removeProduct(product) // Assuming the two products are same. If they aren't you can modify this statement accordingly.
}
}
fun cancelRemoval() { // You can call this function from the click listener
job?.cancel()
}
此外,在您的这行代码中 CoroutineScope(Dispatchers.Main).launch(Dispatchers.Default, CoroutineStart.DEFAULT)
,
- 您不应该t/needn不自己创建新的协程作用域。您 can/should 使用已经提供的
viewModelScope
或 lifecycleScope
。它们是更好的选择,因为它们了解生命周期并在正确的时间被取消。
Dispatchers.Main
没用,因为它无论如何都会被 Dispatchers.Default
取代。 Dispatchers.Default
在这里也不是必需的,因为您在这里没有进行任何繁重的计算(或调用一些阻塞代码)。
CoroutineStart.DEFAULT
是默认参数,因此您可以跳过该参数。
而且你也不需要检查 if (this.isActive)
因为
If the [Job] of the current coroutine is cancelled or completed while delay
is waiting, it immediately resumes with [CancellationException].
所以当我按下一个按钮时,我需要等待 3 秒才能执行另一个方法,我用下面的方法解决了这个问题
val job = CoroutineScope(Dispatchers.Main).launch(Dispatchers.Default, CoroutineStart.DEFAULT) {
delay(THREE_SECONDS)
if (this.isActive)
product?.let { listener?.removeProduct(it) }
}
override fun onRemoveProduct(product: Product) {
job.start()
}
现在,如果我在开始工作后立即按下取消按钮,我就会停止工作,而且工作正常
override fun onClick(v: View?) {
when(v?.id) {
R.id.dismissBtn -> {
job.cancel()
}
}
}
问题是,当我再次执行 onRemoveProduct
执行 job.start()
时,它不会再次启动,似乎 job.isActive
永远不会屈服于 true,为什么会这样?
A Job
一旦取消就无法再次开始。你需要以不同的方式做到这一点。一种方法是每次调用 onRemoveProduct
时创建一个新作业。
private var job: Job? = null
fun onRemoveProduct(product: Product) {
job = scope.launch {
delay(THREE_SECONDS)
listener?.removeProduct(product) // Assuming the two products are same. If they aren't you can modify this statement accordingly.
}
}
fun cancelRemoval() { // You can call this function from the click listener
job?.cancel()
}
此外,在您的这行代码中 CoroutineScope(Dispatchers.Main).launch(Dispatchers.Default, CoroutineStart.DEFAULT)
,
- 您不应该t/needn不自己创建新的协程作用域。您 can/should 使用已经提供的
viewModelScope
或lifecycleScope
。它们是更好的选择,因为它们了解生命周期并在正确的时间被取消。 Dispatchers.Main
没用,因为它无论如何都会被Dispatchers.Default
取代。Dispatchers.Default
在这里也不是必需的,因为您在这里没有进行任何繁重的计算(或调用一些阻塞代码)。CoroutineStart.DEFAULT
是默认参数,因此您可以跳过该参数。
而且你也不需要检查 if (this.isActive)
因为
If the [Job] of the current coroutine is cancelled or completed while
delay
is waiting, it immediately resumes with [CancellationException].