Coroutines: Replacement of AsyncTask Class in Android
What is Coroutines?
Coroutines = Co + Routines
- Here, Co means cooperation and Routines means functions.
- It means that when functions cooperate with each other is called Coroutines.
- Coroutines make writing asynchronous and non-blocking code easy to read and understand by eliminating the need to handle traditional callback pattern.
- It working is conceptually similar to a thread that it takes a block of code to run that works concurrently with the rest of the code. However, a coroutine is not bound to any particular thread. It may suspend its execution in one thread and resume in another one.
- Coroutines can be thought of as light-weight threads, but not thread.
- Coroutines is our recommended solution for asynchronous programming on Android, because AsyncTask class is deprecated in Android with Kotlin Programming now.

Coroutines Features
- Lightweight
- Built-in cancellation support
- Fewer memory leaks
- Jetpack integration
Types of Coroutines
There are two type so Coroutines
- Stackless: don’t have own stack
- Stackful: have own stack
Kotlin implements stackless Coroutines
Coroutines vs Thread
- Coroutines executes within a thread or execute threads
- Coroutines are suspendable
- They can switch their context (Thread Switching)
- Coroutine is as a light-weight thread. Run like threads in parallel, wait for each other and communicate.
- The biggest difference is that Coroutines are very cheap, almost free: we can create thousands of them, and pay very little in terms of performance.
- But true threads, on the other hand, are expensive to start and keep around. A thousand threads can be a serious challenge for a modern machine.
Coroutines Components
- Suspend Functions
- Coroutine Context
- Coroutine Scope
- Dispatchers
- Coroutine Builders: 1. Launch, 2. Async, 3. runBlocking
- Job
Suspend Functions
- A suspend function is simply a function that can be paused and resumed at a later time. They can execute a long running operation and wait for it to complete without blocking.
- The syntax of a suspend function is similar to that of a regular function except for the addition of the suspend keyword. It can take a parameter and have a return type.
suspend fun backgroundTask(param: Int): Int {
// long running operation
}
- Suspend functions can only be invoked by another suspend function or within a coroutine.
Coroutine Context
- CoroutineContext is the execution environment to run/execute Coroutine code asyncronously.
- Every coroutine in Kotlin has a context that is represented by an instance of CoroutineContext interface.
- A context is a set of elements and current coroutine context is available via coroutineContext property:
fun main() = runBlocking<Unit> {
println(“My context is: $coroutineContext”)
}
- The context determines on which thread the Coroutines will run like Default, Main, IO, and Unconfined
Coroutine Scope
- CoroutineScope is the interface that define the concept of Scope with Coroutines, to execute a coroutine you need a scope.
- CoroutineScope use Dispatchers to decide Coroutines scope.
Coroutines Dispatchers
- Dispatchers specify in which scope coroutine will work.
- There are 4 dispatchers
- Default: It is recommended to use CPU intensive works such as very costly mathematical computations.
- IO: It is recommended to used IO Intensive works such as Network Call, File IO or socket IO
- Main: It is recommended to use Main thread operations such as updating UI.
- Unconfined: It is not confined for any use-case. It is recommend to use Testing purpose.
Coroutine Builders
- Coroutine builders are functions that help to create a coroutine. They can be called from normal functions because they do not suspend themselves.
- Three coroutine builders are listed below.
- launch: start a coroutine in the background and keep working.
- async: allows to perform an asynchronous task which return a value
- runBlocking: this blocks the current thread and waits for the coroutine to finish execution.
Launch Builder Example
fun main() {
GlobalScope.launch { // launch new coroutine in background and continue
delay(1000L)
println(“World!”)
}
println(“Hello,”) // main thread continues here immediately
runBlocking { // but this expression blocks the main thread
delay(2000L) // … while we delay for 2 seconds to keep JVM alive
}
}
Async Builder Example
fun main() {
val deferredResult: Deferred<String> = GlobalScope.async {
delay(1000L)
“World!”
}
runBlocking {
println(“Hello, ${deferredResult.await()}”)
}
}
runBlocking Builder Example
fun main() {
println(“Hello,”)
// we create a coroutine running the provided suspending lambda
// and block the main thread while waiting for the coroutine to finish its execution
runBlocking {
// now we are inside a coroutine
delay(2000L) // suspends the current coroutine for 2 seconds
} // will be executed after 2 seconds
println(“World!”)
}
Job in Coroutines
- A Job is a cancellable thing with a life-cycle that culminates in its completion. Coroutine job is created with launch coroutine builder. It runs a specified block of code and completes on completion of this block.
- Job control Coroutines using following functions that are available on the Job interface.
- start(): start Coroutines
- join(): hold Coroutines until it finish task
- cancel(): cancel Coroutines
Job Example
val job = GlobalScope.launch(Dispatchers.Default) {
repeat(5)
{
Log.d(TAG, “Coroutines is still working”)
// delay the coroutine by 1sec
delay(1000)
} }
runBlocking {
// waiting for the coroutine to finish it’s work
job.join()
Log.d(TAG, “Main Thread is Running”)
}}
Normal Operations for Main Thread
In Android, Main thread is only capable to run normal operations like UI Interaction, Button Click, and etc

Heavy Operations for Main Thread
- In Android, if we try to run heavy operations as shown in image, Produce ANR (Application Not Responding) Error

Solution 1: Threads to Overcome ANR problems
- Better solution but occupied more recourses as compare to Coroutines

Solution 2: Coroutines to overcome ANR problems
- Optimum Solution, better than threads, occupied less resources

Practical Example in Android Studio:
Loading Image in Image View by Internet on Clicking on Button
Adding Dependence in Module Level Gradle
dependencies {
implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9’
}
Layout Design
Layout before clicking on Load Image Button

Layout After Clicking on Load Image Button

Main Activity Code
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding= ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnImageLoad.setOnClickListener(View.OnClickListener {
getImageByCoroutines()
})
}
private fun getImageByCoroutines()
{
GlobalScope.launch(Dispatchers.IO) {
val urlImage= URL(“https://i.ytimg.com/vi/D6Lbs8ln49s/maxresdefault.jpg")
val httpURLConnection=urlImage.openConnection() as HttpURLConnection
httpURLConnection.connect()
val bitmap=BitmapFactory.decodeStream(httpURLConnection.inputStream)
launch (Dispatchers.Main){
binding.imageView.setImageBitmap(bitmap)
}
}
}
}