suspend function: mi ez, szintaxis és működés a korutinokban

Szerző: IT Sectr Megjelenés: 2026-06-22 Olvasási idő: 9 perc

Suspend function — egy függvény a suspend módosítóval, amely felfüggesztheti a végrehajtását a szál blokkolása nélkül, és később ugyanabban a korutinban folytathatja. A JetBrains Kotlin Docs, 2025 szerint a suspend függvények a korutinok alapvető építőkövei, aszinkronitást biztosítva callback-ek nélkül. Minden suspend függvény egy Continuation-alapú állapotgépre fordul, ami lehetővé teszi a felfüggesztési pontok hatékony kezelését.

Főbb pontok

  • Suspend — Kotlin kulcsszó, amely egy függvényt felfüggeszthetőként (aszinkronként) jelöl meg
  • Continuation — rejtett paraméter, amelyet a fordító minden suspend függvényhez hozzáad az állapot megőrzéséhez
  • Felfüggesztési pontok — más suspend függvények hívásának helyei, ahol a korutin megállhat blokkolás nélkül
  • Állapotgép — a suspend függvény belső reprezentációja, ahol minden felfüggesztési pont egy külön állapot
  • Csak korutinból hívható — suspend függvények csak másik suspend függvényből vagy launch/async-ből hívhatók

Mi az a suspend function a Kotlinban?

Suspend function — egy a suspend kulcsszóval deklarált függvény, amely egy vagy több ponton felfüggesztheti a végrehajtást a szál blokkolása nélkül. Minden suspend függvény hívása egy másik suspend függvényen belül potenciális felfüggesztési pont.

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

A Kotlin fordító az ilyen függvényt állapotgépre fordítja. Minden felfüggesztési pont (másik suspend függvény hívása) egy állapottá (label) válik. Az aktuális szál felszabadul az állapotok között, és a várt művelet befejezése után a végrehajtás a következő állapottól folytatódik.

Megjelenés története

A suspend függvények a Kotlin 1.3-ban (2018) jelentek meg a korutinokkal együtt kísérleti funkcióként, és a Kotlin 1.5-ben (2021) váltak stabillá. Ezelőtt az aszinkronitást Kotlin/Java-ban callback-ek, RxJava és CompletableFuture biztosította. A suspend függvények alternatívát kínáltak lineáris szintaxissal és automatikus szálkezeléssel.

Hogyan működnek a suspend függvények: Continuation és állapotgép

A suspend függvények belső szerkezetének megértése a kulcs a korutinokkal való helyes munkához. A hétköznapi függvényektől eltérően minden suspend függvény osztályra Continuation interfésszel fordul.

Continuation — a rejtett paraméter

A Kotlin fordító egy Continuation típusú paramétert ad hozzá a suspend függvény minden paraméterének végéhez. A Continuation tartalmazza:

  • context — CoroutineContext (diszpécser, job, kontextus elemek)
  • resumeWith — metódus a végrehajtás folytatására eredménnyel vagy kivétellel
  • label — az aktuális állapot indexe az állapotgépben

Állapotgép példával

Tegyük fel, hogy van egy suspend függvényünk két másik suspend függvény hívásával:

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

A fordító állapotgéppé alakítja címkékkel:

kotlin
// Generált kód egyszerűsített reprezentációja
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
        }
    }
}

Kulcsfontosságú megfigyelés: ha a függvény COROUTINE_SUSPENDED értéket ad vissza, az aktuális szál felszabadul. Amikor az aszinkron művelet befejeződik, a Continuation.resumeWith meghívásra kerül, és az állapotgép a következő label-től folytatja.

Suspend függvények szintaxisa: deklarálás és hívás

A suspend függvény deklarálása nem különbözik a hétköznapitól, kivéve a suspend kulcsszót a fun előtt. Csak egy korlátozás van: suspend függvény csak korutinból vagy másik suspend függvényből hívható.

Alap deklarálás

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

Ebben a példában a delay is egy suspend függvény, amely felfüggeszti a korutint a megadott ezredmásodpercre anélkül, hogy blokkolná a szálat. A késleltetés után a végrehajtás folytatódik.

Hívás korutinból

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

A runBlocking hidat képez a hétköznapi világ és a korutinok között. A lambdán belül bármely suspend függvény hívása engedélyezett.

Suspend lambdák és funkcionális típusok

A Kotlin támogatja a funkcionális típusok suspend verzióit — suspend () -> T és suspend (A) -> B. Ez lehetővé teszi aszinkron lambdák átadását magasabb rendű függvényeknek:

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

A withRetry függvény egy suspend lambdát fogad el, és hiba esetén megismétli a végrehajtását. Ez tipikus minta hálózati kérésekhez újrapróbálkozásokkal.

Miben különböznek a suspend függvények a hétköznapiaktól

A suspend és hétköznapi függvények közötti különbségek túlmutatnak a módosító egyszerű hozzáadásán. Vizsgáljuk meg az alapvető különbségeket.

JellemzőHétköznapi függvénySuspend függvény
Végrehajtási szálBlokkolja a szálat a befejezésigFelszabadíthatja a szálat és később folytathatja
Fordító paramétereiCsak a megadott paraméterekImplicit Continuation a végén
Hívás hétköznapi függvénybőlIgenNem
VeremA szál fizikai vermeÁllapotgép a heap-en + fizikai verem a pontok között
VisszatérésKözvetlen értékÉrték vagy COROUTINE_SUSPENDED
TeljesítményMinimális többletköltség~néhány nanoszekundum az állapotgépért (Kotlin 1.9+)

Miért nem hívhatók suspend függvények hétköznapi függvényekből

A hétköznapi függvénynek nincs Continuationja — nincs hova menteni az állapotot és mivel folytatni a végrehajtást. Ha egy suspend függvényt kell hívnia egy hétköznapi függvényből, használja a runBlocking-ot (tesztekhez) vagy a CoroutineScope.launch-ot (éles használatra, figyelembe véve az életciklust).

Suspend függvény példák Androidban

Vizsgáljuk meg a suspend függvények használatának három valós forgatókönyvét Android alkalmazásokban Kotlinnal.

1. példa: Room DAO suspend lekérdezésekkel

A Room közvetlenül támogatja a suspend függvényeket — a lekérdezés automatikusan a háttérben fut:

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

    @Insert
    suspend fun insertUser(user: User)
}

A Room belsőleg a Dispatchers.IO-t használja a lekérdezés végrehajtásához, és az eredmény abba a diszpécserbe kerül vissza, ahol a suspend függvényt hívták.

2. példa: Suspend függvények kompozíciója képernyő betöltéséhez

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

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

A ViewModelScope.launch létrehoz egy korutint, amelyen belül a getProfile suspend függvény meghívásra kerül. Az eredmény megszerzése után a UI a fő szálon frissül.

3. példa: Szekvenciális aszinkron lépések

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

Három suspend függvény szekvenciálisan hajtódik végre. Minden lépésnél a korutin megállhat a szál blokkolása nélkül. Ha egy lépés kivételt dob — a többiek nem hajtódnak végre, ami véd a rendelés helytelen állapotaitól.

Tipikus hibák a suspend függvények használatakor

Még tapasztalt Kotlin fejlesztők is hibáznak a suspend függvények tervezésekor. Nézzük a leggyakoribbakat.

1. hiba: Blokkoló hívások a suspend-en belül

A suspend függvény nem teszi a kódot automatikusan aszinkronná. A Thread.sleep(), InputStream.read() és más blokkoló hívások továbbra is blokkolják a szálat. Használja a withContext(Dispatchers.IO)-t a blokkoló műveletek becsomagolásához.

2. hiba: Suspend függvények létrehozása szükségtelenül

Ha egy függvény nem hív más suspend függvényeket és nem végez aszinkron műveleteket — a suspend módosító felesleges. Többletköltséget ad az állapotgéphez és korlátozza a hívási kontextust. Csak akkor tegye a függvényt suspend-é, ha az ténylegesen felfüggeszt.

3. hiba: A CancellationException figyelmen kívül hagyása

A korutin megszakításakor a suspend függvények CancellationException-t dobnak. Ne fogja be gondolkodás nélkül — megfosztja a hívó kódot a megszakítás helyes befejezésének lehetőségétől. Ha véglegesítő műveletet kell végrehajtania, használja a finally blokkot és a NonCancellable-t.

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

A finally blokk mindig végrehajtódik, beleértve a megszakítást is, és a NonCancellable garantálja, hogy a takarítás nem szakad meg.

4. hiba: Suspend függvények hívása callback-ekből

Nem hívható suspend függvény közvetlenül callback-ből korutin létrehozása nélkül. Használja a suspendCoroutine-t vagy a suspendCancellableCoroutine-t a callback stílus korutinokhoz való igazításához.

Gyakran Ismételt Kérdések

Tartalmazhat-e egy suspend függvény felfüggesztési pontok nélkül?

Igen, technikailag egy suspend függvény nem hívhat más suspend függvényeket. A fordító egy egy állapotú (label 0) állapotgépet hoz létre. Azonban egy ilyen függvénynek nincs gyakorlati haszna — úgy hajtódik végre, mint egy hétköznapi, de többletköltséggel. Ne használja a suspend-et szükségtelenül.

Hogyan lehet hibakeresni a suspend függvényeket?

A Kotlin biztosítja a kotlinx-coroutines-debug könyvtárat — DebugProbes-szel és korutin nyomkövető eszközökkel. Az Android Studio Arctic Fox verziójától kezdve van egy beépített Coroutines fül a Debugger-ben, amely megjeleníti az aktív korutinokat, azok állapotát és felfüggesztési pontjait.

Befolyásolja-e a suspend pontok száma a teljesítményt?

Minden felfüggesztési pont létrehoz egy új állapotot az állapotgépben. A legtöbb alkalmazás számára egy pont többletköltsége nanoszekundumokban mérhető (Kotlin 1.9+). Csak amikor több tízezer pont van egy ciklusban, érdemes a műveleteket kombinálni vagy sequence/flow-t használni.

Miben különbözik a suspend függvény az async/await-től más nyelvekben?

Kotlinban a suspend a függvény típusának módosítója, nem a visszatérési érték jelölője (mint az async C#-ban). Bármely suspend függvénynek lehet tetszőleges paramétere és visszatérési típusa, és a hívása szintaktikailag nem különbözik egy hétköznapi függvény hívásától — nincs await operátor a hívás helyén.

Hogyan lehet átalakítani egy callback függvényt suspend-é?

Használja a suspendCancellableCoroutine-t az adaptáláshoz. Belül átadja a callback regisztrációt, amely meghívja a continuation.resume()-et, és visszaad egy megszakítási tokent, ha a callback támogatja a leiratkozást. Ez a szabványos minta régi Android API-k becsomagolásához.

Összefoglalás

  • Suspend function — függvény a suspend módosítóval, amely felfüggesztheti a végrehajtást a szál blokkolása nélkül a Continuation mechanizmuson keresztül
  • Állapotgép — a suspend függvény belső reprezentációja Kotlin bájtkódban, ahol minden felfüggesztési pont egy külön állapot label-lel
  • Continuation — rejtett paraméter, amely tartalmazza a korutin kontextusát és a resumeWith metódust a végrehajtás folytatásához
  • Csak korutinból hívható — a suspend függvények nem érhetők el hétköznapi függvényekből runBlocking vagy CoroutineScope nélkül
  • Blokkoló műveletek a suspend-en belül withContext(Dispatchers.IO)-t igényelnek — különben a szál blokkolódik
  • Room és Retrofit natívan támogatják a suspend függvényeket, automatikusan kezelve a háttérszálakat
  • CancellationException — kezelje a megszakítást finally + NonCancellable segítségével, ne fogja be a CancellationException-t gondolkodás nélkül

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is