Coroutine Context

Harjot Singh
4 min readOct 10, 2022

--

Hey, before jumping into this article…make sure you have visited my previous article which describes the basics of what coroutine actually is:

Generally, coroutines are always started in a specific context and context determines in which thread the coroutine will be executed in.

CONTEXT determines in which thread the coroutine will be executed in.

For the sake of example, we’ll start our coroutine using GlobalScope.
(Note: Using global scope is highly discouraged, it should be used only when needed)
More on Scopes and Coroutine Builders in upcoming blogs.

For now, just remember GlobalScope.launch{} will create a coroutine.

If we look at the arguments of the launch builder, you’d notice it takes CoroutineContext as the first argument.

Dispatchers are responsible for determining the context for coroutine.
There are four types of Dispatchers:

  • Dispatchers.Main: This will start coroutine in main thread and is used to perform UI operations within the coroutine.
  • Dispatchers.IO: This will start coroutine in a background thread and is useful for all kind of data operations i.e. Network calls, DB queries, reading and writing to files.
  • Dispatchers.Default: This starts the coroutine in Default thread and is useful for complex and long-running tasks that might block the main thread resulting in freezing of the UI.
  • Dispatchers.Unconfined: It is appropriate for coroutines which neither consume CPU time nor perform any UI operations i.e. not confined to any specific thread. In simple terms, it is used for an operation which ain’t heavy but still for some reason you want to run on a different thread.

Now, the question arises…if network call is done in different thread and UI is updated in different thread, then how does that happen? How does coroutine handle it?
The answer is simple. Remember, coroutine can switch their contexts…and let me jog your memory…context determines in which thread to execute the coroutine. Hence, coroutine can switch context from IO thread to Main thread.

Before getting into the good stuff, let’s understand…what is suspend?

The functions with ‘suspend’ modifier are called suspend functions.

Kidding 😅
Suspend here means a function that can be started, paused or resumed.

In the article below, we discussed about the coroutines and how is it different from threads. The point that coroutines are suspendable is explained well in this article.

Point to be noted is : Suspend functions can only be called from another suspend function or from a coroutine.

Let’s look at an example:

// Starts Coroutine in IO thread
(a) GlobalScope.launch(Dispatchers.IO) {
Log.d(TAG, "This is thread: ${Thread.currentThread().name}")
(b) delayForSomeTime()
// Can switch context i.e. thread
// Now switched to main thread, basically should be used for getting answer from background thread
// and updating UI thread
(c) withContext(Dispatchers.Main) {
(d) binding
.tvText.text = "The text is changed now"
Log.d(TAG, "This is thread:${Thread.currentThread().name}")
}
}
Log.d(TAG, "This is thread: ${Thread.currentThread().name}")
}
private suspend fun delayForSomeTime() {
delay(3000)
Log.d(TAG, "Delaying for some time")
}

Explanation of code:

(a) — This creates a new coroutine in IO a.k.a background thread. Dispatchers.IO is what determines in which thread the coroutine should be executed in. GlobalScope here refers to the scope of this coroutine i.e. this coroutine will exist as long as the lifetime of parent scope (in this case the entire lifetime of application).
This will be discussed thoroughly in future blogs.

(b) — delayForSomeTime() calls delay() which is another suspend function. Remember, a suspend function can only be called from another suspend function or a coroutine. So from a coroutine we called delayForSomeTime suspend method and within it we called another suspend function( delay() ). This will pause the coroutine for 3 secs.
Note: This is not the appropriate way to pause a coroutine. We’d be using Job.join().
More on this later.

(c) — using withContext we can switch our contexts i.e. switch to different threads. Consider delayForSomeTime() as a network call…after this call happens we are switching our context from IO thread to Main thread since UI operations can only happen in the main thread.

(d) — I’ve used viewBinding concept here, i.e. binding.tvText.text will change the text for TextView.

Basically, we are creating a coroutine in IO thread and then switch to Main thread and update the UI.

Output:

Output

Please do show your support by clapping for the blog. More blogs on this topic coming your way.
Until then happy coding!

--

--

Harjot Singh

Android Developer @HealhifyMe I lose my handwritten notes often...so now making sure I can find my notes easily :p