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.
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.
fun doAction(view: View) {
Thread(start = true) {
executeLongRunningTask()
}
}
Why Not Ideal:
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.
We need two things to run coroutine.
What: A dispatcher decides which thread(s) a coroutine will use for its execution.
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}")
}
}
lifecycleScope, viewModelScope) to prevent leaks.