DEV Community

RohanG-Dev
RohanG-Dev

Posted on

Kotlin Coroutine Scopes in Android

Introduction

Before we understand what are Coroutine Scopes . Lets understand first what is a Coroutine.

What is Coroutines ?
-> Coroutines is a tool/framework which manages the Concurrency in a simple and efficient way .
Co + Routines = Coroutines -> Co means Cooperation and Routines means functions .
It means 2 or more functions Cooperate with each other in a non-blocking(asynchronous) manner to accomplish its
respective task.

So in Android development ,Coroutines are used to achieve non-blocking(asynchronous) code Execution .

What are Coroutines Scopes?
-> IN order to decide the lifecycle of a Coroutine we need Coroutine Scopes . Basically Coroutines Scopes are restriction
within which a Coroutine has to execute and It's very important to understand under which scope should a coroutine be executed.

We have 4 types of Coroutine Scopes

  1. GlobalScope
  2. LifecycleScope
  3. ViewModelScope
  4. CoroutineScope

GlobalScope

The Coroutine launched within the GlobalScope will stay alive till the Application is NOT destroyed.

The Coroutine launched in the GlobalScope will always be launched in a separate[worker] thread.

Now suppose the Coroutine launched in globalscope is performing some task/operation and then suddenly the application is destroyed then the coroutine will also die . Since the lifetime of the Coroutine is same as the lifetime of the Application.

But there is a problem with launching coroutine with globalscope inside a lifecycle component [eg:activity/fragment] .
When a Coroutine is launched with a globalScope inside a activity the coroutine will not die when the activity is destroyed.
Since the lifetime of Coroutine is same as the lifetime of the application and not the lifetime of the activity.

Now since the coroutine is using resources of the activity in which it is launched , so when the activity is destroyed the resources will not be garbage collected as coroutine is still holding on to those resources .
This leads to problem called Memory Leak.

So its not recommended to use globalScope always .

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ....
        ....

        GlobalScope.launch {
            // Coroutinue launched. do some task.
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

LifecycleScope

The Coroutine launched within the LifecycleScope will stay alive till the Lifecycle owner[activity/fragment] is NOT destroyed.

When the activity/fragment is destroyed the coroutines will also die, as the Lifetime of LifecycleScope is same as the Lifetime of the Lifecycle owner[activity/fragment].

By using LifecycleScope we DONT have to do manually check and cancel the running Coroutine before the Lifecycle owner is destroyed.

Eg:


class MainActivity : AppCompatActivity(){

    override fun onCreate(savedInstanceState: Bundle?) {
        ....
        ....
        lifecycleScope.launch {
                // Coroutinue launched. do some task.
            }

        }

}
Enter fullscreen mode Exit fullscreen mode

ViewModelScope

The Coroutine launched within the ViewModelScope will stay alive till the ViewModel is NOT cleared.

The ViewModelScope is similar to LifecycleScope except it happens on ViewModel. So when the ViewModel is cleared the Coroutine will also die as the Lifetime of ViewModelScope is same as the Lifetime of the ViewModel .

By using ViewModelScope we DONT have to do manually check and cancel the running Coroutine before
the ViewModel is cleared.

Eg:

class MainViewModel : ViewModel
{
   fun doSomeTask(){
        viewModelScope.launch{
            // Coroutinue launched. do some task.
        }
   }
}
Enter fullscreen mode Exit fullscreen mode

CoroutineScope

If the User wants to run a long running task and after sometime if user doesn't intend to use it anymore then we should be able to stop it at some point to avoid the task from wasting cpu & memory resources. In Coroutine we can avoid such problem by keeping Track of the task and limit its lifetime using CoroutineScope.

By using CoroutineScope we can keep track of the work and cancel the task when not needed.

Eg:

class Repo
{
    lateinit var coroutinescope : CoroutineScope

    fun doSomeTask(){
            coroutinescope = CoroutineScope(Dispatchers.Main)
            coroutinescope.launch {
                // Coroutinue launched. do some task.
            }
    }

    fun cancelTask(){
        if(::coroutinescope.isInitialized && coroutinescope.isActive)
        {
            coroutinescope.cancel() 
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion:

In Conclusion: Usage of Scopes
1) GlobalScope - If you want to run coroutine in the Application Scope.
2) LifecycleScope - If you want to run coroutine in the Lifecycle owner [activity/fragment]
3) ViewModelScope - If you want to run coroutine in ViewModel.
4) CoroutineScope - If you want to run coroutine in places other than ViewModel or Lifecycle owner[activity/fragment]

Keep Learning..Keep Growing !!!
Thank You :)


Enter fullscreen mode Exit fullscreen mode

Latest comments (0)