Threads, Main Thread & Kotlin Coroutines

A very good article on coroutines

1. Main Thread (UI Thread)

What: The main thread (also called the UI thread) is where Android executes UI-related tasks — drawing, event handling, and lifecycle methods.

Why: It ensures that all UI operations happen sequentially and safely, avoiding race conditions or UI corruption.

How: The main thread internally runs a Looper and MessageQueue. The Looper waits for tasks or messages in the queue and executes them one by one.

2. Example of Blocking the UI Thread

fun doAction(view: View) {
    executeLongRunningTask() // Blocks main thread
}

private fun executeLongRunningTask() {
    for (i in 1..1_000_000_000L) {
        // Long computation
    }
}

Effect: The UI freezes and may cause an Application Not Responding (ANR) error.

3. Fix Using a Background Thread

fun doAction(view: View) {
    Thread(start = true) {
        executeLongRunningTask()
    }
}

Why Not Ideal:

4. Kotlin Coroutines

What: Lightweight, cooperative routines that can run multiple tasks on the same thread without blocking it.

Why: Threads are limited and costly; coroutines are managed by Kotlin runtime and can run thousands of tasks concurrently.

How: Coroutines suspend instead of blocking — when waiting, they yield control so other coroutines can run.

5. Coroutine Scope & Context

We need two things to run coroutine.

6. Dispatchers

What: A dispatcher decides which thread(s) a coroutine will use for its execution.

7. Example Using Dispatchers

fun doAction(view: View) {
    CoroutineScope(Dispatchers.IO).launch {
        Log.d(TAG, "Running on: ${Thread.currentThread().name}")
    }

    GlobalScope.launch(Dispatchers.Main) {
        Log.d(TAG, "Running on: ${Thread.currentThread().name}")
    }

    MainScope().launch(Dispatchers.Default) {
        Log.d(TAG, "Running on: ${Thread.currentThread().name}")
    }
}

8. Common Coroutine Scopes

9. Summary