Igor
Igor

Reputation: 134

How to use coroutines in a Kotlin Library

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

Answers (2)

Sam Chen
Sam Chen

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

J.Grbo
J.Grbo

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

Related Questions