Zoltan Demant
08/17/2022, 6:30 AMGlobalScope.launch {} or `scope.launch(context = NonCancellable) {}`; or are they basically the same thing? My operation is just a few millis long.Stylianos Gakis
08/17/2022, 8:44 AMJob object out of it and attaching a invokeOnCompletion on it?
Smth like
val myScope: CoroutineScope
myScope.coroutineContext[Job]?.invokeOnCompletion {
delay()
}Zoltan Demant
08/17/2022, 8:46 AMNick Allen
08/17/2022, 5:16 PMCoroutineScope, we are talking about lifetimes of work and/or resources and the relationship between those lifetimes. So the answer depends on how your lifetimes are relate to each other.
Reserve GlobalScope for singleton's and resources that last the entire process. If your component has work with one lifetime and some other work with another, then feel free to use multiple `CoroutineScope`s (though it can also be a warning that you should split up your class).
I would never use scope.launch(context = NonCancellable) {}, calling launch with a context that contains a Job is confusing. I mean, if you aren't using the scope's job, why use it at all? If scope is cancelled, would this even run or no?
I probably wouldn't use GlobalScope.launch {} directly since if I'm using global resources (the only time I'd use GlobalScope) then I'd probably wrap those resources into a singleton and so I'd be calling a non-suspend method that calls GlobalScope.launch internally so invokeOnCompletion would work. But don't use GlobalScope to clean up resources owned by the component, you lose the ability to wait on scope to know when those resources are actually freed.
If I had work lifetime and a work+cleanup lifetime. I'd might go with something like:
val componentScope = CoroutineScope() //or however you define it
//Cancelling componentScope will also cancel workScope due to child/parent Jobs
//Waiting for componentScope, waits for work + cleanup to all finish
val workScope = CoroutineScope(SupervisorJob(componentScope.coroutineContext.job))
init {
//UNDISPATCHED ensures it starts before cancellation could possibly happen
componentScope.launch(start = CoroutineStart.UNDISPATCHED) {
withContext(NonCancellable) { // clearer than passing it into launch
workScope.join() //wait for all work to finish
cleanUpSuspending()
}
}
}Zoltan Demant
08/18/2022, 3:29 AMAlbert Chang
08/18/2022, 3:37 AMfinally block?
If you only want to do it when the coroutine is cancelled, then:
try {
...
} catch (e: CancellationException) {
cleanUp()
throw e
}Zoltan Demant
08/18/2022, 3:50 AMZoltan Demant
08/18/2022, 3:53 AMZoltan Demant
08/18/2022, 3:55 AMNick Allen
08/18/2022, 5:19 AM