Using withContext in Kotlin Coroutines

withContext is a suspending function used to switch the coroutine context (dispatcher) for a block of code. It is commonly used for performing background tasks like IO or CPU-intensive work and then returning the result to the original context.

1️⃣ Basic Syntax


val result = withContext(Dispatchers.IO) {
    // Code here runs on IO dispatcher
    someComputation()
}
  

The block runs in the specified dispatcher, and the coroutine resumes on its original context after completion.

2️⃣ Why Use withContext?

3️⃣ Example 1 — Switching to IO Dispatcher


import kotlinx.coroutines.*

fun main() = runBlocking {
    println("Running on thread: ${'$'}{Thread.currentThread().name}")

    val result = withContext(Dispatchers.IO) {
        println("Running on thread: ${'$'}{Thread.currentThread().name}")
        delay(1000) // Simulate long-running IO task
        "Data from IO"
    }

    println("Result: ${'$'}result")
    println("Back to thread: ${'$'}{Thread.currentThread().name}")
}
  

Output:

Running on thread: main
Running on thread: DefaultDispatcher-worker-1
Result: Data from IO
Back to thread: main
  

Explanation: The coroutine switches to a background thread for IO, then resumes on the main thread.

4️⃣ Example 2 — CPU-Intensive Computation


val sum = withContext(Dispatchers.Default) {
    var total = 0
    for (i in 1..5_000_000) total += i
    total
}
println("Sum: ${'$'}sum")
  

Explanation: Heavy computation runs on Dispatchers.Default to avoid blocking the main thread.

5️⃣ Example 3 — Nested Context Switching


runBlocking {
    println("Start on: ${'$'}{Thread.currentThread().name}")

    withContext(Dispatchers.IO) {
        println("IO work on: ${'$'}{Thread.currentThread().name}")

        withContext(Dispatchers.Default) {
            println("CPU work on: ${'$'}{Thread.currentThread().name}")
        }
    }

    println("Back to start thread")
}
  

Explanation: You can nest withContext blocks to switch between different dispatchers for IO and CPU work.

6️⃣ launch vs withContext

Feature launch withContext
Returns Job (no result) Result of the block
Can switch thread Only if dispatcher is specified Explicitly switches context
Suspension No, runs concurrently Suspends until block finishes
Use-case Fire-and-forget tasks Get a result from background work

7️⃣ TL;DR

withContext is used to switch coroutine context safely for a block of code, perform work like network calls or heavy computation off the main thread, and return a result. It keeps structured concurrency intact and allows proper cancellation handling.