Open PhilippNowak96 opened 10 months ago
This is happening to me as well in a similar way, did you manage to find a solution around this?
The only way I found was the one I mentioned above. Use CoroutineScope(Dispatchers.Main).launch(exceptionHandler) {...}
directly. In addition you can take the Job
it returns and make sure to cancel it by yourself in the ViewModel's onCleared
method. That should put you on the safe side.
The mvvm.viewmodel viewModelScope context does not include a SupervisorJob() which means if the job executed through viewModelScope is canceled, its child jobs will also be canceled.
private val ioDispatchers = SupervisorJob() + Dispatchers.IO
viewModelScope.launch(ioDispatchers) {
block() // Even if an exception occurs, viewModelScope will not be canceled.
}
I have the similar issue. Using runcatching{}.onfailure{}
can help in this case but this is not idea as it breaks structured concurrency since Cancellation exception is captured. You can always rethrow it but then why have structured concurrency 🤷
Is someone planning to fix this?
Cause
The mvvm.viewmodel viewModelScope context does not include a SupervisorJob() which means if the job executed through viewModelScope is canceled, its child jobs will also be canceled.
Solution
private val ioDispatchers = SupervisorJob() + Dispatchers.IO viewModelScope.launch(ioDispatchers) { block() // Even if an exception occurs, viewModelScope will not be canceled. }
This is not the solution. It is highly discouraged to use custom Job
instances when launching new coroutines. Passing a job instance to launch as a coroutine context will override its parent job, not the newly created coroutine's job making it an entry point to unstructured concurrency. These top-level coroutines should be able to be managed through CoroutineExceptionHandler
instance.
Here Roman Elizarov's article about it in more depth
If you use
viewModelScope.launch {}
with aCoroutineExceptionHandler
and an exception occurs, the same function does not run anymore when triggered again.Repro
(
Logger
is fromimplementation("co.touchlab:kermit:2.0.0-RC5")
)The
doSomething
function is triggered on compose button click. First run outputs as expected:If you then click the button again, only
Trying to do something...
appears, so theviewModelScope.launch
is not executed anymore.If you change the
doSomething()
function to useCoroutineScope
directly, everything works as expected: