Consider the following example:
var job: Job? = null
fun foo() {
job = launch(UI) {
val bar = download().await()
// Cancel could have been called now
// The following code is posted to the Handler
performSomeWorkOnTheUI(bar)
}
}
override fun onPause() {
job?.cancel()
}
Cancelling the job
in onPause
will make await
throw, but when it is cancelled after await
has returned, things will go wrong. Since performSomeWorkOnTheUi(bar)
is posted as a Runnable
to a Handler
associated with the main thread, the UI may be already paused and thus unavailable when the function is invoked.
The only way I found to avoid this issue was wrapping the call to performSomeWorkOnTheUI
inside if (isActive)
. Since the check is posted to the Handler
as well, it is running on the UI thread. I’m wondering if there’s a cleaner way to do this, since it’s easy to forget checking isActive
after code has been posted to a Handler
. Ideally, the coroutine library would check for me whether the job was cancelled after the continuation resumes on the UI thread, but of course before the code that follows the await()
runs.