Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JobCancellationException StandaloneCoroutine was cancelled

Since we are using Coroutines (1.3.5 used) we have a lot of crash : JobCancellationException - StandaloneCoroutine was cancelled.

I read a lot of thread about theses problems and I tried a lot of solution in production but crashes always occurs.

In all our viewmodels we are using the viewmodelscope so it's ok.

But in our data layer we need to launch a tracking events which are fire and forget task. In first step we used a GlobalScope.launch. I was thinking the CancelletationException was due to this global scope so I removed it and create an extension in the data layer with using a SupervisorJob and a CoroutineExceptionHandler:

private val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
private val coroutineExceptionHandler by lazy { CoroutineExceptionHandler { _, throwable -> logw("Error occurred inside Coroutine.", throwable) } }

fun launchOnApp(block: suspend CoroutineScope.() -> Unit) {
    appScope.launch(coroutineExceptionHandler) { block() }
}

But I always saw crashes with this code. Do I need to use cancelAndJoin method? Which strategy I can use with a clean archi and this kind of work please?

Thanks in advance

like image 809
Pierre Avatar asked Mar 18 '20 14:03

Pierre


People also ask

What happens to a coroutine when job cancel is called?

Once job.cancel is called, our coroutine moves to Cancelling state. But then, we see that Hello 3 and Hello 4 are printed to the terminal. Only after the work is done, the coroutine moves to Cancelled state. The coroutine work doesn’t just stop when cancel is called.

How do you handle a cancellationexception when a coroutine is cancelled?

Since a CancellationException is thrown when a coroutine is cancelled, then we can wrap our suspending work in try/catch and in the finally block, we can implement our clean up work. println (“Work cancelled!”) println (“Clean up!”)

What is coroutineexceptionhandler in Java?

CoroutineExceptionHandler is a last-resort mechanism for global "catch all" behavior. You cannot recover from the exception in the CoroutineExceptionHandler. The coroutine had already completed with the corresponding exception when the handler is called.

How do I cancel a job in jetpack?

Use the CoroutineScopes defined in Jetpack: viewModelScope or lifecycleScope that cancels their work when their scope completes. If you’re creating your own CoroutineScope, make sure you’re tying it to a job and calling cancel when needed.


1 Answers

You can build an extension utility that catches the cancellation exception, and do what you want with it:

fun CoroutineScope.safeLaunch(block: suspend CoroutineScope.() -> Unit): Job {
  return this.launch {
    try {
      block()
    } catch (ce: CancellationException) {
      // You can ignore or log this exception
    } catch (e: Exception) {
      // Here it's better to at least log the exception
      Log.e("TAG","Coroutine error", e)
    }
  }
}

And you can use the extension with a coroutine scope of your choice, for example the global scope:

GlobalScope.safeLaunch{
  // here goes my suspend functions and stuff
}

or any viewmodel scope:

myViewModel.viewModelScope.safeLaunch{
// here goes my suspend functions and stuff
}
like image 73
Simone Avatar answered Sep 20 '22 12:09

Simone