Kotlin Coroutines Cheat Sheet
Covers launching coroutines, suspend functions, coroutine builders, structured concurrency with scopes, and Flow for asynchronous Kotlin code.
2 PagesIntermediateMar 30, 2026
Coroutine Builders
launch and async, the two primary ways to start a coroutine.
kotlin
import kotlinx.coroutines.*fun main() = runBlocking { // launch: fire-and-forget coroutine, returns a Job val job = launch { delay(1000L) println("World!") } println("Hello,") job.join() // wait for the coroutine to finish // async: returns a Deferred<T>, use .await() to get the result val deferred: Deferred<Int> = async { delay(500L) 21 } println("Answer: ${deferred.await() * 2}")}
Suspend Functions
Functions that can be paused and resumed without blocking a thread.
kotlin
// suspend functions can call other suspend functions and be paused/resumedsuspend fun fetchUser(id: Int): String { delay(300) // non-blocking delay, suspends the coroutine return "User$id"}suspend fun fetchAndPrint(id: Int) { val user = fetchUser(id) // suspension point println(user)}// suspend functions can only be called from a coroutine or another suspend funfun main() = runBlocking { fetchAndPrint(1)}
Coroutine Dispatchers
Controlling which thread(s) a coroutine runs on.
- Dispatchers.Main- Runs on the UI thread (Android/desktop UI frameworks); for UI updates
- Dispatchers.IO- Optimized for blocking I/O like network calls and file access, large thread pool
- Dispatchers.Default- Optimized for CPU-intensive work (sorting, parsing), sized to CPU cores
- Dispatchers.Unconfined- Starts in the caller's thread, resumes in whatever thread the suspension used
- withContext(Dispatcher)- Switches the coroutine's dispatcher for a block, then switches back
- newSingleThreadContext()- Creates a dedicated single-thread dispatcher for confinement
Structured Concurrency
Scoping coroutines so they can't outlive their parent unexpectedly.
kotlin
import kotlinx.coroutines.*class UserRepository { // CoroutineScope tied to this class's lifecycle private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) fun loadUsers() { scope.launch { val users = fetchUsers() // child coroutine println(users) } } fun cancelAll() { scope.cancel() // cancels all children started in this scope }}suspend fun fetchUsers(): List<String> = coroutineScope { // coroutineScope suspends until all children complete; propagates errors val a = async { fetchUser(1) } val b = async { fetchUser(2) } listOf(a.await(), b.await())}
Flow Basics
Cold asynchronous streams of values built on coroutines.
kotlin
import kotlinx.coroutines.flow.*fun countdown(from: Int): Flow<Int> = flow { for (i in from downTo 1) { delay(100) emit(i) // suspending emission of the next value }}suspend fun main() { countdown(3) .map { it * 10 } .filter { it > 10 } .collect { value -> println(value) } // terminal operator, starts the flow}// StateFlow: hot, state-holder flow with an initial valueval state = MutableStateFlow(0)state.value = 1
Pro Tip
Prefer structured concurrency (coroutineScope, viewModelScope, or a scope tied to a lifecycle) over GlobalScope.launch — GlobalScope coroutines outlive their caller and are a common source of leaks and untracked crashes.
Was this cheat sheet helpful?
Explore Topics
#KotlinCoroutines#KotlinCoroutinesCheatSheet#Programming#Intermediate#CoroutineBuilders#SuspendFunctions#CoroutineDispatchers#StructuredConcurrency#Functions#Concurrency#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance