Why Using GlobalScope Is Discouraged In Kotlin-Coroutines?

Why Using GlobalScope Is Discouraged?

  • When We Use GlobalScope To Launch A Coroutine It Will be Launched In Top-Level Coroutine As It's Global And It Will Be Remained Until Your Application Is Dead.

In Other Words:

  • If You Are Using GlobalScope To Launch A Coroutine It Will Be Alive Until Your Application Is Dead Even You Have Skipped The Particular Activity || Fragment Where That Particular Corotuine Has Been Launched.

  • As You Already Know That Coroutines Are Light-Weight But Still It Will Consume Some Memory Resources While It's Running For Sure, Which May Cause Memory Leaks In Your Application.

Solution

  • You Can Use Pre-Defined Scopes Such As lifecycleScope{...} And If You Are Working With ViewModel(s) You Can Use viewModelScope{...} To Launch A Coroutine And Get Started.

Practical Difference

Let's Test With Both GlobalScope{...} And lifecycleScope{...} For Better Understanding

  • I Have Created Two Fragments And Added Navigation Between Both Fragments Through Navigation Component.

First Fragment's XML:

Second Fragment's XML:

Time For The Truth🔥

Before Moving To Further Make Sure That You Have Included Coroutines Dependency If It's Not Included:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'

In First Fragment's Kotlin File:

With GlobalScope{...}

  • Primarily Coroutine Will Be Launched Asusal With GlobalScope{...} When Button Is Pressed.

  • When Button Will Be Pressed An Infinite Loop Will Run With A Second Delay every time.

  • After 5 Seconds Delay, Second Fragment Will Be Launched As You Can See Below In The Code:

view.toSecondFragment.setOnClickListener {
       GlobalScope.launch{
         while (true) {
              delay(1000L)
              Log.d("From GlobalScope", "Global Scope Is Still Running")
     }
 }

      GlobalScope.launch(Dispatchers.Main){
         delay(5000L)
         Navigation.findNavController(view).navigate(R.id.firstFragment_to_secondFragment)
      }
}
  • Now Launch The Application After A Successful Build:
  • As You Can See That Even Though First Fragment Has Dead Our Loop Still Continues As We Declared Our Scope As GlobalScope{...} Which Will Continues To Run Until Our Application Is Dead.

  • This Is The Main Reason Why Using GlobalScope Is Discouraged In Kotlin-Coroutines.

With lifecycleScope{...}

  • Primarily Coroutine Will Be Launched Asusal With lifecycleScope{...} When Button Is Pressed.

  • When Button Will Be Pressed An Infinite Loop Will Run With A Second Delay every time.

  • After 5 Seconds Delay, Second Fragment Will Be Launched.

As You Can See In The Code That I Have Mentioned viewLifecycleOwner Before Launching The Coroutine With lifecycleScope{...}

  • It's Because I am Working With Fragments. viewLifecycleOwner Is Added When The Fragment Has Its UI ( onCreateView() , onDestroyView() ) This Is Added To The Fragment's Overall Lifecycle ( onCreate() , onDestroy() ).

  • In case, If You Are Working With Activities You Don't Need To Mention viewLifecycleOwner.

view.toSecondFragment.setOnClickListener {
            viewLifecycleOwner.lifecycleScope.launch{
                while (true) {
                    delay(1000L)
                    Log.d("From LifeCycleScope", "LifeCycleScope Is Still Running")
                }
            }
           viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main){
                delay(5000L)
                Navigation.findNavController(view).navigate(R.id.firstFragment_to_secondFragment)
            }
        }
  • Now Launch The Application After A Successful Build:
  • As You Can See That Once The Fragment Has Dead Coroutine Execution Has Stopped.

Same Implies To viewModelScope{...} As Well, It Will Also Perform Same As lifecycleScope{...}.** But You'll Be Using viewModelScope{...} When you Are Working With ViewModel(s).

Conclusion

  • Use GlobalScope{...} When You Want An Operation To Run Until The Application Is Dead If Not You Should Definitely Use lifecycleScope{...}.

  • If You Are Working With ViewModel(s) You Can Use viewModelScope{...}.

Well, That's All For Now🙌

Bye🤗

22