Reputation: 134
how do i correctly use coroutines in a Library class which has nothing to do with the activity lifecycle?
For now, i created a private property in my class:
private val coroutineScope = CoroutineScope(Dispatchers.Main)
and have a cancel method, to cancel the scope.
public fun cancel() {
coroutineScope.coroutineContext.cancelChildren()
}
Is there any cleaner way to make this work, without having to call cancel on my library class in onPause/OnStop?
EDIT:
Also, an additional question: Does it matter, if my created CoroutineContext is in a Singleton? Like this:
public object MyObject {
private val coroutineScope = CoroutineScope(Dispatchers.Main)
}
Is there any danger of memory leaks or similar?
Upvotes: 2
Views: 1569
Reputation: 8907
how do i correctly use coroutines in a Library class which has nothing to do with the activity lifecycle?
Well, I would recommend you don't create coroutineScope
inside your library class
, instead you turn your class function into suspend
function by specifying which thread (Dispatcher) it should run on:
suspend fun doWork() {
withContext(Dispatchers.IO) { //run on IO thread
//do your stuff
}
}
AND THEN, use built-in coroutineScope
like viewModelScope
from ViewModel
, or lifecycleScope
from Activity / Fragment
to execute this suspend
function. Those built-in coroutineScopes
will be auto-canceld after the ViewModel
or Activity / Fragment
get destroyed, so you don't need to worry about them:
viewModelScope.launch {
myLibrayObject.doWork() //<- suspend function, you decide the thread inside this function
}
Upvotes: 2
Reputation: 475
Simply said no, you create a scope when you need it, you cancel it when you don't need it anymore. Scope takes care of the lifecycle of all the coroutines
fired from it. A coroutine is an instance of suspendable computation. Once you do not need that computation anymore you cancel it, in order to save computational power where it's really needed. To avoid tracking all the fired coroutine by their jobs, we have a scope. Imagine having 1000 independent coroutines and having to track 1000 jobs to cancel them, instead of that, we have a scope to cancel them all at once. You can simply call scope.cancel()
.
One way how you can avoid manually calling cancel()
in onPause/onStop
is to use observation pattern, make your library class implement LifecycleObserver
interface and have it observe the Lifecycle
of an Activity/Fragment
of interest.
A Singleton is just a single ever existing instance of a class, there's no reason why would there be any problems having CoroutineScope
instance inside of it.
Upvotes: 3