Coroutine Contexts In Kotlin

Coroutine Contexts In Kotlin

·

4 min read

Before Getting Started I Suggest You Understand What's Actually A Suspend Function Is, Which I Have Discussed In The Previous Blog In This Series. And Make Sure That You Have Included Coroutines Dependency If It's Not Included:

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

-> Every Coroutine Launches With A Specific Context And This Context Will Describe That In Which A Specific Thread/Coroutine Will Launch In.

->So Far In This Series We Have Only Used GlobalScope.launch{ } To Launch A New Coroutine Which Doesn't Give Full Flexibility Which We Want.

  • To Overcome That Limitations We Have Something Known As Dispatchers

Now, What Is Mean By Dispatchers🤔?

Dispatchers Determine What thread or threads the corresponding coroutine uses for its execution.

->All coroutine builders like launch and async accept an optional CoroutineContext parameter that can be used to explicitly specify the dispatcher for the new coroutine.

  • We Have 4 Dispatchers Which Are Used For Different Things:

    • Dispatchers.Main

    • Dispatchers.IO

    • Dispatchers.Default

    • Dispatchers.Unconfined

More Details:

1. Dispatchers.Main : Main Dispatcher Allows Us To Control UI Elements From A Coroutine Which Will Be Executed As The Main Thread From A Coroutine Itself.

-> But How Can We Implement Main Dispatcher🤔?

-It's Simple:

GlobalScope.launch(Dispatchers.Main) {
//Code
}

In Android Studio Your Code May Look Like This👇🏼

Note: All Of The Green Coloured Marks Are Being Highlighted By Me Not By The IDE, So In Your IDE You Won't See Any Highlighting Which You Can See Below: Main Dispatcher Implementation.png

-> You Can Use Log To Check Whether Main Dispatcher Is Running In MainDispatcher Or Not:

GlobalScope.launch(Dispatchers.Main) {
            Log.d("mainCoroutine","Running In ${Thread.currentThread().name}")
}

->After Successful Launch Of Your Application, Open Logcat To Clarify It.

Running From Main Coroutine.png

-As You Can See That It Is Executing In Main Dispatcher As We Declared It As Main Dispatcher.

->But How Can We Control UI After Specifying Main Dispatcher🤔?

-You Can Use Viewbinding, Synthetics, Extensions[Depricated], Or Other Alternatives For Controlling UI From A Coroutine After Specifying Main Dispatcher.

Example:-

->In My .XML File I Have Added A Simple TextView:

text added.png

->And In The .kt File, I Have Specified A Block Of Code Which Will Change The Text, Inside The Coroutine Including Main Dispatcher So That I Can Work With UI.

changing the textView.png

And Launching The Application After Successful Build:

Main Dispatcher Changing The Text.gif -As You Can See That It Works Like Charm🥳

->But In Case If You Didn't Specify Main Dispatcher If You Want To Control UI Elements From A Coroutine, You'll Get This Beautiful Error In Your Logcat After Launching The Application Which Says:

logcat errror.png

This Error Occurs If You Didn't Mention It As Main Dispatcher. Because UI Elements Can Be Controlled Only From The Main Thread.

2. Dispatchers.IO : IO Dispatcher Is Used To Control || Execute All Those Data Operations Such As Networking, Writing/Adding Data In Database(s), Reading || Writing The Files.

-> But How Can We Implement IO Dispatcher🤔?

-It's Simple:

GlobalScope.launch(Dispatchers.IO) {
//Code
}

3. Dispatchers.Default : Default Dispatcher Can Be Used To Run Long Operations || Long Tasks Which Will Make Main Thread As A Unresponsiveness. To Avoid Unresponsiveness In Your App, You Can Use Default Dispatcher.

-> But How Can We Implement Default Dispatcher🤔?

-It's Simple:

GlobalScope.launch(Dispatchers.Default) {
//Code
}

4. Dispatchers.Unconfined : Unconfined Dispatcher Is Not Confined To Any Specific Thread. In Other Words, The Unconfined Dispatcher Is Appropriate For coroutines That Neither Consume CPU Time Nor Update Any Shared Data (like UI) Confined To A Specific Thread.

-> But How Can We Implement Unconfined Dispatcher🤔?

-It's Simple:

GlobalScope.launch(Dispatchers.Unconfined) {
//Code
}

-> In Case, If You Are Thinking That Is It Possible To Launch Multiple Coroutines From The Same Coroutine Builder Including Dispatchers?

And The Answer Is:

Yes, It's Possible:

  • I Have Assigned Log So That We'll Be Knowing That, AreThese Really Executing In Coroutine Dispatcher's Or Not.
GlobalScope.launch {
            delay(1000L)
            launch(Dispatchers.Main) {
                Log.d("multipleLaunches", "Running In ${Thread.currentThread().name}")
            }
            delay(1000L)
            launch(Dispatchers.IO) {
                Log.d("multipleLaunches", "Running In ${Thread.currentThread().name}")
            }
            delay(1000L)
            launch(Dispatchers.Default) {
                Log.d("multipleLaunches", "Running In ${Thread.currentThread().name}")
            }
            delay(1000L)
            launch(Dispatchers.Unconfined) {
                Log.d("multipleLaunches", "Running In ${Thread.currentThread().name}")
            }
        }

And As You Can See That Multiple Launches From The Same Coroutine Builder Works Like Charm🥳:

multiple launches.png Well That's All For Now, In Upcoming Blog I'll Discuss runBlocking😉

Bye🤗