code:
viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "task 1")
}) {
try {
Log.e("TAG", "task 1 start")
delay(3000)
Log.e("TAG", "task 1 finished")
} catch (ex: Exception) {
Log.e("TAG", "task 1 cancelled " + ex)
}
}
launch = viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "handler 1" + myJob?.isCancelled)
}) {
myJob = SupervisorJob()
launch(myJob!! + CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "handler 2 " + myJob?.isCancelled)
}) {
delay(300)
launch {
try {
Log.e("TAG", "task 2 start")
delay(5000)
Log.e("TAG", "task 2 finished")
} catch (ex: Exception) {
Log.e("TAG", "task 2 ex " + ex)
}
}
launch {
delay(2000)
throw Exception()
}
}
launch {
try {
Log.e("TAG", "task 3 start")
delay(3000)
Log.e("TAG", "task 3 finished")
} catch (ex: Exception) {
Log.e("TAG", "task 3 ex " + ex)
}
}
}
output:
2020-01-06 09:47:56.462 7159-7159/? E/TAG: task 1 start
2020-01-06 09:47:56.496 7159-7159/? E/TAG: task 3 start
2020-01-06 09:47:56.798 7159-7159/com.mvvm.template.debug E/TAG: task 2 start
2020-01-06 09:47:58.822 7159-7159/com.mvvm.template.debug E/TAG: task 2 ex kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; job=StandaloneCoroutine{Cancelling}@81a8e39
2020-01-06 09:47:58.827 7159-7159/com.mvvm.template.debug E/TAG: handler 2 false
2020-01-06 09:47:59.464 7159-7159/com.mvvm.template.debug E/TAG: task 1 finished
2020-01-06 09:47:59.499 7159-7159/com.mvvm.template.debug E/TAG: task 3 finished
my issue:
I’m having an issue to understand why task 2 is canceled when it’s a child of SupervisorJob and the exception happened on an other child.
The documentation state:
A failure or cancellation of a child does not cause the supervisor job to fail and does not affect its other children, so a supervisor can implement a custom policy for handling failures of its children. Am i missing something or what ? any help would be appreciated.
I’m having an issue to understand why task 2 is canceled when it’s a child of SupervisorJob and the exception happened on an other child.
Here this is not a direct answer to the question as it's already answered well by the accepted answer as the parent is not the SupervisorJob
But in order to achieve the intended behavior of making task2 independent of the sibling jobs:
You've to use SupervisorJob by either:
SupervisorJob the parent of each task that you want to be independent of one another:In your example:
val myJob = SupervisorJob()
val launch = viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "handler 1" + myJob.isCancelled)
}) {
launch(CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "handler 2 " + myJob.isCancelled)
}) {
delay(300)
launch(myJob) { // <<<<<<<<< myJob is the parent
try {
Log.e("TAG", "task 2 start")
delay(5000)
Log.e("TAG", "task 2 finished")
} catch (ex: Exception) {
Log.e("TAG", "task 2 ex $ex")
}
}
launch(myJob) { // <<<<<<<<< myJob is the parent
delay(2000)
throw Exception()
}
}
//......
}
supervisorScope suspend functionval launch = viewModelScope.launch(CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "handler 1")
}) {
launch(CoroutineExceptionHandler { _, _ ->
Log.e("TAG", "handler 2 ")
}) {
delay(300)
supervisorScope { /// <<<< supervisor scope
launch {
try {
Log.e("TAG", "task 2 start")
delay(5000)
Log.e("TAG", "task 2 finished")
} catch (ex: Exception) {
Log.e("TAG", "task 2 ex $ex")
}
}
launch {
delay(2000)
throw Exception()
}
}
}
//....
}
Now task 2 will complete without raising JobCancellationException
Your answer is right there in the log:
task 2 ex kotlinx.coroutines.JobCancellationException: Parent job is Cancelling;
job=StandaloneCoroutine{Cancelling}@81a8e39
Look at the parent job: it's a StandaloneCoroutine and not your SupervisorJob.
When you write
launch(myJob!!, handler) { ... }
myJob becomes the parent of the launched coroutine and the coroutine itself is always associated with a job the launch function creates for it, of the type StandaloneCoroutine. Inside this coroutine you launch more coroutines without explicitly specifying a parent, which means their parent is the coroutine's job. It is not a supervisor job and gets canceled.
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