Hi all. Just a (maybe newbie) question. Why MainSc...
# coroutines
m
Hi all. Just a (maybe newbie) question. Why MainScope() uses a SupervisorJob? Which are the advantages? In general if there is an uncontrolled exception in my app I want it to crash because it can enter an uncontrolled state (break fast). I'm missing something?
a
Most (if not everytime), the
MainScope()
usually is the one hooked to the Main thread. While your use case might wan't you to crash your UI. Most popular use cases are to handle those errors gracefully and display them on (you guessed it), a UI. So, thats why
MainScope()
uses a
SupervisorJob()
u
Does SupervisorJob prevent the app from crashing? I thought it would just prevent one failing child from canceling it’s siblings
a
If that one child fails (throws), it doesn't cancel the whole scope. If it was a regular Job, then when a child coroutine fails, it cancels the whole scope and now the UI can't do any more work, hence it crashes
u
UI can't do any more work, hence it crashes
???
a
May you be specific on what you need clarifications on?? I can make my own assumptions and assume I fully understand your question but I'd rather have you clarify your contradiction
u
Sorry, I thought it was clear. I did not understand how not having any coroutines running to do work for the UI is related to crashing.
a
Oooh, I see. Let me go into details further. Starting with Job vs SupervisorJob then we'll go to the mainscope. When a coroutine that has been launched without a
CoroutineExceptionHandler
crashes (Not cancelled, Crashes), it cancels the Job. Any subsequent launches to this Job will throw (which if not handled properly, will crash the system), This behaviour is not the same for a
SuoervisorJob.
if a similar coroutine is launched and crashes, subsequent launches from this SupervisorJob won't throw (cause it was never cancelled). Now, to the
MainScope()
Most UI frameworks (if not all), launch their UI related tasks from the main scope. If the MainScope was backed by a
Job
any further tasks launched by the UI (i.e event scheduling and painting, and even Layouting) would be throwing a CoroutineCancelledException (Do not quote me on that). But because the MainScope is backed by a
SupervisorJob
(and not a regular job) it supports subsequent launches even where there are child coroutines failing or they are being cancelled
u
I think some of your above statements are not exactly true. Definitely they miss the point. The cause for the app crash (at least for Android) is very simple and not related to canceled scopes: https://medium.com/androiddevelopers/exceptions-in-coroutines-ce8da1ec060c
If the exception is not handled and the
CoroutineContext
doesn’t have a
CoroutineExceptionHandler
(as we’ll see later), it will reach the default thread’s
ExceptionHandler
. In the JVM, the exception will be logged to console; and in Android, it will make your app crash regardless of the Dispatcher this happens on.
The point is, Using a SupervisorJob does not prevent your App from crashing if you don’t catch your exceptions. Installing a
CoroutineExceptionHandler
could be a solution though.
a
I am well aware of the
CoroutineExceptionHandler
as I mentioned above, the whole context is about coroutines which have't been supplied a
CoroutineExceptionHandler
There are plenty of uses cases where one would consciously opt not to pass a
CoroutineExceptionHandler
but thats not the topic. Putting all that into context, now point out to me exactly which statement is not exactly true. I'd like to relearn if relearning is due
Yes yes yes, you are right. I see it now through your explanations. it will crash despite the dispatcher you use. So, SupervisorJob is only about perfoming subsequent lanches even when there are some previous coroutine children cancelled