When we have a coroutine scope, when it is canceled, can it be used again?
e.g. for the below, when I have scope.cancel
, the scope.launch
no longer work
@Test
fun testingLaunch() {
val scope = MainScope()
runBlocking {
scope.cancel()
scope.launch {
try {
println("Start Launch 2")
delay(200)
println("End Launch 2")
} catch (e: CancellationException) {
println("Cancellation Exception")
}
}.join()
println("Finished")
}
}
Similarly, when we have scope.cancel
before await
called,
@Test
fun testingAsync() {
val scope = MainScope()
runBlocking {
scope.cancel()
val defer = scope.async {
try {
println("Start Launch 2")
delay(200)
println("End Launch 2")
} catch (e: CancellationException) {
println("Cancellation Exception")
}
}
defer.await()
println("Finished")
}
}
It will not execute. Instead, it will crash with
kotlinx.coroutines.JobCancellationException: Job was cancelled
; job=SupervisorJobImpl{Cancelled}@39529185
at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:1579)
at kotlinx.coroutines.CoroutineScopeKt.cancel(CoroutineScope.kt:217)
at kotlinx.coroutines.CoroutineScopeKt.cancel$default(CoroutineScope.kt:215)
at com.example.coroutinerevise.CoroutineExperiment$testingAsync$1.invokeSuspend(CoroutineExperiment.kt:241)
at |b|b|b(Coroutine boundary.|b(|b)
at kotlinx.coroutines.DeferredCoroutine.await$suspendImpl(Builders.common.kt:101)
at com.example.coroutinerevise.CoroutineExperiment$testingAsync$1.invokeSuspend(CoroutineExperiment.kt:254)
Caused by: kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelled}@39529185
at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:1579)
at kotlinx.coroutines.CoroutineScopeKt.cancel(CoroutineScope.kt:217)
at kotlinx.coroutines.CoroutineScopeKt.cancel$default(CoroutineScope.kt:215)
at com.example.coroutinerevise.CoroutineExperiment$testingAsync$1.invokeSuspend(CoroutineExperiment.kt:241)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
Is it true, a canceled coroutine scope cannot be used for launch
or async
anymore?
cancelAndJoin() // cancels the job and waits for its completion println("main: Now I can quit.") like the following example shows: val startTime = System. currentTimeMillis() val job = launch(Dispatchers.
ViewModelScope. A ViewModelScope is defined for each ViewModel in your app. Any coroutine launched in this scope is automatically canceled if the ViewModel is cleared.
To use Kotlin Coroutine, we need to have the appropriate scope defined. The tricky bit of it is, we have to remember to create, and stop them. In view of that, the Google Android development team has provided us with some Coroutine Scopes that are aware of its lifecycle.
When we launch a coroutine in Kotlin using launch we are returned the resulting Job . We can wait for the coroutine to finish by calling join() on the Job.
Instead of using CoroutineScope
for cancelling all of the launched jobs in it, you may want to use the underlying CoroutineContext
with its cancelChildren()
method which doesn't affect the Job
state (which is not true for plain cancel()
method) and allows to continue launching new coroutines after being invoked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With