Suspend Functions

The suspend Keyword

A function marked suspend can call other suspend functions such as delay, withContext or a Retrofit API call. It can be called only from a coroutine or from another suspend function.

  • suspend does not make code run in the background by itself. It only means "this function may pause".
  • Inside, code still runs top to bottom, like normal code. No callbacks.
  • Calling a suspend function from a normal function is a compile error: Suspend function should be called only from a coroutine or another suspend function.

Sequential by Default

Example

Two suspend calls run one after another, exactly like normal code. The total time is the sum.

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

suspend fun fetchUserName(id: Int): String {
    delay(300)                   // pretend network call
    return "User#$id"
}

suspend fun fetchOrderCount(name: String): Int {
    delay(200)
    return name.length
}

fun main() = runBlocking {
    val time = measureTimeMillis {
        val name = fetchUserName(7)
        val orders = fetchOrderCount(name)
        println("$name has $orders orders")
    }
    println("Took at least 500 ms: ${time >= 500}")
}

Output

User#7 has 6 orders
Took at least 500 ms: true

Behind the Scenes

The compiler adds a hidden Continuation parameter. Roughly:

// What you write
suspend fun fetchUserName(id: Int): String

// What the JVM sees (simplified)
fun fetchUserName(id: Int, cont: Continuation<String>): Any?
// returns either the result, or COROUTINE_SUSPENDED and later calls cont.resume(result)

Tip: Name suspend functions like normal functions (loadProfile(), not loadProfileAsync()). The suspend modifier already tells the caller it may wait.

Practice

Exercise: Write a suspend function downloadFile(name: String): Int that waits 100 ms and returns the length of the name. Call it for "a.txt" and "report.pdf" from main and print the total.

Show answer
import kotlinx.coroutines.*

suspend fun downloadFile(name: String): Int {
    delay(100)
    return name.length
}

fun main() = runBlocking {
    val total = downloadFile("a.txt") + downloadFile("report.pdf")
    println("Total: $total")   // Total: 15
}