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 AMNick Allen
08/18/2022, 5:19 AM