suspend function: co to je, syntax a fungování v korutinách

Autor: IT Sectr Publikováno: 2026-06-22 Doba čtení: 9 min

Suspend function — je funkce s modifikátorem suspend, která může pozastavit své provádění bez blokování vlákna a později pokračovat ve stejné korutině. Podle JetBrains Kotlin Docs, 2025 jsou suspend funkce základním stavebním kamenem korutin, poskytujícím asynchronnost bez callbacků. Každá suspend funkce je kompilována do stavového stroje založeného na Continuation, což umožňuje efektivní správu bodů pozastavení.

Hlavní body

  • Suspend — klíčové slovo Kotlin, které označuje funkci jako pozastavitelnou (asynchronní)
  • Continuation — skrytý parametr, který kompilátor přidává ke každé suspend funkci pro uchování stavu
  • Body pozastavení — místa volání jiných suspend funkcí, kde se korutina může zastavit bez blokování
  • Stavový stroj — interní reprezentace suspend funkce, kde každý bod pozastavení je samostatný stav
  • Volání pouze z korutiny — suspend funkce lze volat pouze z jiné suspend funkce nebo z launch/async

Co je suspend function v Kotlin?

Suspend function — je funkce deklarovaná klíčovým slovem suspend, která může pozastavit provádění v jednom nebo více bodech bez blokování vlákna. Každé volání suspend funkce uvnitř jiné suspend funkce je potenciální bod pozastavení.

kotlin
suspend fun fetchUserData(): User {
    val response = httpClient.get("/user")
    return parser.parse(response)
}

Kompilátor Kotlin překládá takovou funkci do stavového stroje. Každý bod pozastavení (volání jiné suspend funkce) se stává stavem (label). Aktuální vlákno je uvolněno mezi stavy a po dokončení očekávané operace provádění pokračuje od následujícího stavu.

Historie vzniku

Suspend funkce se objevily v Kotlin 1.3 (2018) spolu s korutinami jako experimentální funkce a staly se stabilními v Kotlin 1.5 (2021). Před tím byla asynchronnost v Kotlin/Java zajišťována pomocí callbacků, RxJava a CompletableFuture. Suspend funkce nabídly alternativu s lineární syntaxí a automatickým řízením vláken.

Jak fungují suspend funkce: Continuation a stavový stroj

Porozumění vnitřní struktuře suspend funkcí je klíčem ke správné práci s korutinami. Na rozdíl od běžných funkcí je každá suspend funkce kompilována do třídy s rozhraním Continuation.

Continuation — skrytý parametr

Kompilátor Kotlin přidává parametr typu Continuation na konec každého parametru suspend funkce. Continuation obsahuje:

  • context — CoroutineContext (dispečer, job, prvky kontextu)
  • resumeWith — metoda pro obnovení provádění s výsledkem nebo výjimkou
  • label — index aktuálního stavu ve stavovém stroji

Stavový stroj na příkladu

Předpokládejme, že máme suspend funkci se dvěma voláními jiných suspend funkcí:

kotlin
suspend fun process() {
    val a = stepOne()
    val b = stepTwo(a)
    println(b)
}

Kompilátor ji převede na stavový stroj s nálepkami:

kotlin
// Zjednodušená reprezentace vygenerovaného kódu
fun process(cont: Continuation<Unit>): Any? {
    val cont = cont as ProcessContinuation
    when (cont.label) {
        0 -> {
            cont.label = 1
            if (stepOne(cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
        }
        1 -> {
            cont.label = 2
            val a = cont.result as TypeA
            if (stepTwo(a, cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
        }
        2 -> {
            println(cont.result)
            Unit
        }
    }
}

Klíčové pozorování: pokud funkce vrátí COROUTINE_SUSPENDED, aktuální vlákno je uvolněno. Po dokončení asynchronní operace je zavoláno Continuation.resumeWith a stavový stroj pokračuje od dalšího labelu.

Syntaxe suspend funkcí: deklarace a volání

Deklarace suspend funkce se neliší od běžné, kromě klíčového slova suspend před fun. Existuje pouze jedno omezení: suspend funkci lze volat pouze z korutiny nebo jiné suspend funkce.

Základní deklarace

kotlin
suspend fun delayAndReturn(ms: Long): String {
    delay(ms)
    return "Done after ${ms}ms"
}

V tomto příkladu je delay také suspend funkce, která pozastaví korutinu na zadaný počet milisekund bez blokování vlákna. Po zpoždění je provádění obnoveno.

Volání z korutiny

kotlin
fun main() = runBlocking {
    val result = delayAndReturn(1000)
    println(result)
}

runBlocking vytváří most mezi běžným světem a korutinami. Uvnitř lambdy je povoleno volání libovolných suspend funkcí.

Suspend lambdy a funkční typy

Kotlin podporuje suspend verze funkčních typů — suspend () -> T a suspend (A) -> B. To umožňuje předávat asynchronní lambdy funkcím vyššího řádu:

kotlin
suspend fun  withRetry(
    retries: Int = 3,
    block: suspend () -> T
): T {
    repeat(retries - 1) {
        try { return block() }
        catch (_: Exception) { delay(100) }
    }
    return block()
}

Funkce withRetry přijímá suspend lambdu a opakuje její provádění při chybách. Toto je typický vzor pro síťové požadavky s opakováním.

Čím se suspend funkce liší od běžných

Rozdíly mezi suspend a běžnými funkcemi přesahují prosté přidání modifikátoru. Podívejme se na zásadní rozdíly.

CharakteristikaBěžná funkceSuspend funkce
Vlákno prováděníBlokuje vlákno do dokončeníMůže uvolnit vlákno a pokračovat později
Parametry kompilátoruPouze uvedené parametryImplicitní Continuation na konci
Volání z běžné funkceAnoNe
ZásobníkFyzický zásobník vláknaStavový stroj na haldě + fyzický zásobník mezi body
NávratPřímá hodnotaHodnota nebo COROUTINE_SUSPENDED
VýkonMinimální režie~pár nanosekund na stavový stroj (Kotlin 1.9+)

Proč nelze suspend funkce volat z běžných funkcí

Běžná funkce nemá Continuation — nemá kam uložit stav a čím obnovit provádění. Pokud potřebujete zavolat suspend funkci z běžné, použijte runBlocking (pro testy) nebo CoroutineScope.launch (pro produkci s ohledem na životní cyklus).

Příklady suspend funkcí v Android

Podívejme se na tři reálné scénáře použití suspend funkcí v Android aplikacích v Kotlin.

Příklad 1: Room DAO se suspend dotazy

Room přímo podporuje suspend funkce — dotaz se provádí automaticky na pozadí:

kotlin
@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :id")
    suspend fun getUser(id: Int): User?

    @Insert
    suspend fun insertUser(user: User)
}

Room interně používá Dispatchers.IO pro provedení dotazu a výsledek je vrácen dispečerovi, ve kterém byla suspend funkce zavolána.

Příklad 2: Kompozice suspend funkcí pro načtení obrazovky

kotlin
class ProfileViewModel : ViewModel() {
    private val repo = ProfileRepository()

    fun loadProfile(id: String) {
        viewModelScope.launch {
            val profile = repo.getProfile(id)
            _profile.value = profile
        }
    }
}

ViewModelScope.launch vytváří korutinu, uvnitř které je volána suspend funkce getProfile. Po získání výsledku je UI aktualizováno na hlavním vlákně.

Příklad 3: Sekvenční asynchronní kroky

kotlin
suspend fun placeOrder(cart: Cart): OrderResult {
    val validated = validateCart(cart)
    val payment = processPayment(validated)
    val receipt = sendReceipt(payment)
    return receipt
}

Tři suspend funkce se provádějí sekvenčně. V každém kroku se korutina může zastavit bez blokování vlákna. Pokud některý krok vyvolá výjimku — ostatní se neprovedou, což chrání před nesprávnými stavy objednávky.

Typické chyby při práci se suspend funkcemi

Dokonce i zkušení vývojáři Kotlin dělají chyby při navrhování suspend funkcí. Podívejme se na nejčastější.

Chyba 1: Blokující volání uvnitř suspend

Suspend funkce nedělá kód automaticky asynchronním. Thread.sleep(), InputStream.read() a další blokující volání stále zablokují vlákno. Použijte withContext(Dispatchers.IO) pro zabalení blokujících operací.

Chyba 2: Vytváření suspend funkcí bez potřeby

Pokud funkce nevolá jiné suspend funkce a neprovádí asynchronní operace — modifikátor suspend je nadbytečný. Přidává režii na stavový stroj a omezuje kontext volání. Dělejte funkci suspend pouze tehdy, když se skutečně pozastavuje.

Chyba 3: Ignorování CancellationException

Při zrušení korutiny suspend funkce vyvolávají CancellationException. Nechytejte ho bezmyšlenkovitě — připravujete volající kód o možnost správně dokončit zrušení. Pokud potřebujete provést finalizující operaci, použijte blok finally a NonCancellable.

kotlin
suspend fun safeOperation() {
    try {
        doWork()
    } finally {
        withContext(NonCancellable) {
            cleanup()
        }
    }
}

Blok finally se vždy provede, včetně zrušení, a NonCancellable zaručuje, že čištění nebude přerušeno.

Chyba 4: Volání suspend funkcí z callbacků

Nelze volat suspend funkci přímo z callbacku bez vytvoření korutiny. Použijte suspendCoroutine nebo suspendCancellableCoroutine pro adaptaci callback stylu na korutiny.

Často kladené otázky

Může suspend funkce neobsahovat body pozastavení?

Ano, technicky suspend funkce nemusí volat jiné suspend funkce. Kompilátor vytvoří stavový stroj s jedním stavem (label 0). Taková funkce však nemá praktický užitek — provádí se jako běžná, ale s režií. Nepoužívejte suspend zbytečně.

Jak ladit suspend funkce?

Kotlin poskytuje kotlinx-coroutines-debug — knihovnu s DebugProbes a nástroji pro sledování korutin. V Android Studio od verze Arctic Fox je vestavěná karta Coroutines v Debuggeru, která zobrazuje aktivní korutiny, jejich stav a body pozastavení.

Ovlivňuje počet suspend bodů výkon?

Každý bod pozastavení vytváří nový stav ve stavovém stroji. Pro většinu aplikací je režie jednoho bodu v jednotkách nanosekund (Kotlin 1.9+). Teprve při desítkách tisíc bodů ve smyčce stojí za to kombinovat operace nebo použít sequence/flow.

Čím se liší suspend funkce od async/await v jiných jazycích?

V Kotlin je suspend modifikátor typu funkce, nikoli označení návratové hodnoty (jako async v C#). Libovolná suspend funkce může mít libovolné parametry a návratový typ a její volání se syntakticky neliší od volání běžné funkce — na místě volání není operátor await.

Jak převést callback funkci na suspend?

Použijte suspendCancellableCoroutine pro adaptaci. Uvnitř předáte registraci callbacku, která volá continuation.resume(), a vrátíte token zrušení, pokud callback podporuje odhlášení. Toto je standardní vzor pro zabalení starých Android API.

Shrnutí

  • Suspend function — funkce s modifikátorem suspend, která může pozastavit provádění bez blokování vlákna prostřednictvím mechanismu Continuation
  • Stavový stroj — interní reprezentace suspend funkce v bytecode Kotlin, kde každý bod pozastavení je samostatný stav s labelem
  • Continuation — skrytý parametr obsahující kontext korutiny a metodu resumeWith pro obnovení provádění
  • Volání pouze z korutiny — suspend funkce nejsou přístupné z běžných funkcí bez runBlocking nebo CoroutineScope
  • Blokující operace uvnitř suspend vyžadují withContext(Dispatchers.IO) — jinak je vlákno blokováno
  • Room a Retrofit nativně podporují suspend funkce, automaticky spravují vlákna na pozadí
  • CancellationException — zpracujte zrušení pomocí finally + NonCancellable, nechytejte CancellationException bezmyšlenkovitě

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také