https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

mingkangpan

03/06/2020, 10:25 AM
Copy code
supervisorScope {
    async {
        throw Exception()
    }

    async {
        throw Exception()    
    }
}
^ app doesn't crash
Copy code
supervisorScope {
    launch {
        throw Exception()
    }

    launch {
        throw Exception()    
    }
}
^ app crashes what am I doing wrong?
m

Manuel Vivo

03/06/2020, 10:36 AM
When
async
has a
SupervisorJob
as a parent (which is in that case), it won’t crash until you call
.await()
.
launch
automatically throws the exceptions as soon as it happens but that’s not the case of
async
. It’ll hold it until you call
await
Notice, that if you change
supervisorScope
for
coroutineScope
, now the parent
Job
of async is of type
Job
(not
SupervisorJob
) and the exception will be propagated as soon as it happens
That’s because a
SupervisorJob
let’s the coroutine handle the exception (and crash if it hasn’t been handled)
An article about this is planned to be published next Wednesday; based on Florina Muntenescu and my talk at KotlinConf
👍 3
m

mingkangpan

03/06/2020, 10:46 AM
@Manuel Vivo could you hep me woth this one?
Copy code
override fun onChanged(t: AccountInfo) {
        fetchDataAfterAccountInfo?.cancel()
        fetchDataAfterAccountInfo = viewModelScope.launch {
            try {
                supervisorScope {
                    launch {
                        val purchases = appService.fetchPurchasesWithPickupData().purchases
                        pickPurchasesLiveData.postValue(purchases)
                    }
                    launch {
                        val paymentPlan = appService.fetchPaymentPlan()
                        paymentPlanLiveData.postValue(paymentPlan.instalments)
                    }
                }
            } catch (e : Exception) {
                Timber.e(e, "loading data after accountInfo failed")
            }
        }
    }
m

Manuel Vivo

03/06/2020, 10:47 AM
supervisorScope
is not going to propagate the exception up to the try/catch, if you want that behavior, use
coroutineScope
m

mingkangpan

03/06/2020, 10:48 AM
everytime after a new accountInfo, I want to load 2 different set if data and put them into livedata if one fails, it should NOT influence the other one but I want to be able to cancel both at same time
how would you code?
m

Manuel Vivo

03/06/2020, 10:50 AM
Then use
supervisorScope
but try/catch the inner launches instead of try/catching the
supervisorScope
call
m

mingkangpan

03/06/2020, 11:00 AM
Copy code
override fun onChanged(info: AccountInfo) {
        fetchDataAfterAccountInfo?.cancel()
        fetchDataAfterAccountInfo = viewModelScope.launch(CoroutineExceptionHandler { _, e -> Timber.e(e, "loading data after accountInfo failed") }) {
            supervisorScope {
                launch {
                    val purchases = appService.fetchPurchasesWithPickupData().purchases
                    pickPurchasesLiveData.postValue(purchases)
                }
                launch {
                    val paymentPlan = appService.fetchPaymentPlan()
                    paymentPlanLiveData.postValue(paymentPlan.instalments)
                }
            }
        }
    }
this should do it right?! 😅
It’s the point of the section. You should never do that
because it’s pointless, it’s not doing anything
m

mingkangpan

03/12/2020, 9:22 AM
why does the method has this argument then?
e

Evan R.

03/12/2020, 12:38 PM
The argument is more for changing the coroutine dispatcher so you can run in a different thread pool, for instance. The proper way to deal with the SupervisorJob would be to define
job
as
CoroutineScope(SupervisorJob())
and then perform multiple
launch {}
invocations off of that so they can still run independently.
I think you can also add a CoroutineExceptionHandler but I could be wrong
5 Views