I have coroutine scope assigned to an activity lifecycle like this
class MainActivity : AppCompatActivity(),
CoroutineScope
{
override val coroutineContext: CoroutineContext =
Dispatchers.Main + SupervisorJob()
...
override fun onDestroy() {
coroutineContext[Job]!!.cancel()
super.onDestroy()
}
}
Now if I launch a CountDownTimer within this scope, it does not get cancelled when activity is destroyed.
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()
}
Why does it not get cancelled? And how to make it get cancelled specifically by cancelling the activity job?
I don't know why you use a coroutine here, but you can get rid of it, save an instance of
CountDownTimer
to a variable and cancel it inonDestroy
method:CountDownTimer
has its own mechanism of handling ticks, usingHandler
. It is not attached to a coroutine's context. Coroutine cancellation is cooperative. A coroutine code has to cooperate to be cancellable. If a coroutine is working in a computation and does not check for cancellation, then it cannot be cancelled.There are a couple of approaches to making computation code cancellable:
delay
.isActive
orensureActive()
.