当其 activity 协程作业被取消时取消 CountDownTimer
Cancel CountDownTimer when its activity coroutine job is cancelled
我已将协程范围分配给这样的 activity 生命周期
class MainActivity : AppCompatActivity(),
CoroutineScope
{
override val coroutineContext: CoroutineContext =
Dispatchers.Main + SupervisorJob()
...
override fun onDestroy() {
coroutineContext[Job]!!.cancel()
super.onDestroy()
}
}
现在,如果我在此范围内启动 CountDownTimer,它不会在 activity 被销毁时被取消。
override fun onCreate(savedInstanceState: Bundle?) {
...
launch {
startTimer()
}
}
fun startTimer(count: Long = 1000) {
object: CountDownTimer(count, 1000) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
startTimer()
}
}.start()
}
为什么没有取消?以及如何通过取消 activity 作业来具体取消它?
不知道为什么这里要用协程,不过可以去掉,把CountDownTimer
的一个实例存到一个变量里,在onDestroy
方法里取消:
lateinit var timer: CountDownTimer
override fun onCreate(savedInstanceState: Bundle?) {
...
startTimer()
}
fun startTimer(count: Long = 1000) {
timer = object: CountDownTimer(count, 1000) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
startTimer()
}
}.start()
}
override fun onDestroy() {
timer.cancel()
super.onDestroy()
}
Why does it not get cancelled?
CountDownTimer
有自己的处理报价的机制,使用 Handler
。它不附加到协程的上下文。
Coroutine cancellation is cooperative。协程代码必须协作才能取消。如果协程正在计算中并且不检查取消,则无法取消。
There are a couple of approaches 使计算代码可取消:
- 第一个是定期调用一个挂起函数来检查取消,例如
delay
.
- 明确检查取消状态,例如
isActive
或 ensureActive()
.
我已将协程范围分配给这样的 activity 生命周期
class MainActivity : AppCompatActivity(),
CoroutineScope
{
override val coroutineContext: CoroutineContext =
Dispatchers.Main + SupervisorJob()
...
override fun onDestroy() {
coroutineContext[Job]!!.cancel()
super.onDestroy()
}
}
现在,如果我在此范围内启动 CountDownTimer,它不会在 activity 被销毁时被取消。
override fun onCreate(savedInstanceState: Bundle?) {
...
launch {
startTimer()
}
}
fun startTimer(count: Long = 1000) {
object: CountDownTimer(count, 1000) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
startTimer()
}
}.start()
}
为什么没有取消?以及如何通过取消 activity 作业来具体取消它?
不知道为什么这里要用协程,不过可以去掉,把CountDownTimer
的一个实例存到一个变量里,在onDestroy
方法里取消:
lateinit var timer: CountDownTimer
override fun onCreate(savedInstanceState: Bundle?) {
...
startTimer()
}
fun startTimer(count: Long = 1000) {
timer = object: CountDownTimer(count, 1000) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
startTimer()
}
}.start()
}
override fun onDestroy() {
timer.cancel()
super.onDestroy()
}
Why does it not get cancelled?
CountDownTimer
有自己的处理报价的机制,使用 Handler
。它不附加到协程的上下文。
Coroutine cancellation is cooperative。协程代码必须协作才能取消。如果协程正在计算中并且不检查取消,则无法取消。
There are a couple of approaches 使计算代码可取消:
- 第一个是定期调用一个挂起函数来检查取消,例如
delay
. - 明确检查取消状态,例如
isActive
或ensureActive()
.