19
Coroutine Contexts In Kotlin
Before Getting Started I Suggest You Understand What's Actually A Coroutine 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:
1.Dispatchers.Main
2.Dispatchers.IO
3.Dispatchers.Default
4.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:
-> 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.
-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:
->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.
And Launching The Application After Successful Build:
->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:
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 Main 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 Main 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 Main 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 Is These 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🥳:
Bye🤗
19