suspend function: ano ito, syntax at paggana sa coroutines

May-akda: IT Sectr Nai-publish: 2026-06-22 Oras ng pagbabasa: 9 min

Suspend function — ay isang function na may suspend modifier na maaaring mag-pause ng pag-execute nito nang hindi hinaharangan ang thread at magpatuloy mamaya sa parehong coroutine. Ayon sa JetBrains Kotlin Docs, 2025, ang mga suspend function ay pangunahing bloke ng pagbuo ng mga coroutine, na nagbibigay ng asynchrony nang walang mga callback. Bawat suspend function ay naka-compile sa isang state machine na batay sa Continuation, na nagpapahintulot ng mahusay na pamamahala ng mga suspension point.

Mga Pangunahing Punto

  • Suspend — keyword ng Kotlin na nagmamarka ng function bilang napapahinto (asynchronous)
  • Continuation — nakatagong parameter na idinaragdag ng compiler sa bawat suspend function para mapanatili ang estado
  • Mga suspension point — mga lugar ng pagtawag sa iba pang suspend function kung saan maaaring huminto ang coroutine nang hindi humaharang
  • State machine — panloob na representasyon ng suspend function, kung saan ang bawat suspension point ay hiwalay na state
  • Tawag lamang mula sa coroutine — ang mga suspend function ay maaari lamang tawagin mula sa ibang suspend function o mula sa launch/async

Ano ang suspend function sa Kotlin?

Suspend function — ay isang function na idineklara gamit ang keyword na suspend na maaaring mag-pause ng pag-execute sa isa o higit pang mga punto nang hindi hinaharangan ang thread. Bawat pagtawag ng suspend function sa loob ng ibang suspend function ay potensyal na suspension point.

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

Isinasalin ng Kotlin compiler ang naturang function sa state machine. Bawat suspension point (pagtawag sa ibang suspend function) ay nagiging isang state (label). Ang kasalukuyang thread ay pinakawalan sa pagitan ng mga state, at pagkatapos makumpleto ang inaasahang operasyon, magpapatuloy ang pag-execute mula sa susunod na state.

Kasaysayan ng paglitaw

Lumitaw ang mga suspend function sa Kotlin 1.3 (taong 2018) kasama ang mga coroutine bilang isang eksperimental na feature at naging stable sa Kotlin 1.5 (taong 2021). Bago ito, ang asynchrony sa Kotlin/Java ay ibinigay sa pamamagitan ng mga callback, RxJava at CompletableFuture. Nag-alok ang mga suspend function ng alternatibo na may linear syntax at awtomatikong pamamahala ng thread.

Paano gumagana ang mga suspend function: Continuation at state machine

Ang pag-unawa sa panloob na istraktura ng mga suspend function ay susi sa tamang paggamit ng mga coroutine. Hindi tulad ng mga ordinaryong function, bawat suspend function ay naka-compile sa isang klase na may Continuation interface.

Continuation — nakatagong parameter

Nagdaragdag ang Kotlin compiler ng parameter na uri ng Continuation sa dulo ng bawat parameter ng suspend function. Ang Continuation ay naglalaman ng:

  • context — CoroutineContext (dispatcher, job, mga elemento ng konteksto)
  • resumeWith — pamamaraan para magpatuloy ng pag-execute na may resulta o exception
  • label — index ng kasalukuyang state sa state machine

State machine na may halimbawa

Ipagpalagay na mayroon tayong suspend function na may dalawang tawag sa iba pang suspend function:

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

Ginagawa ito ng compiler sa state machine na may mga label:

kotlin
// Pinasimpleng representasyon ng nabuong code
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
        }
    }
}

Mahalagang obserbasyon: kung ang function ay nagbalik ng COROUTINE_SUSPENDED, ang kasalukuyang thread ay pinakawalan. Kapag natapos ang asynchronous operation, tinatawag ang Continuation.resumeWith, at magpapatuloy ang state machine mula sa susunod na label.

Syntax ng mga suspend function: deklarasyon at pagtawag

Ang deklarasyon ng suspend function ay hindi naiiba sa ordinaryong function, maliban sa keyword na suspend bago ang fun. Mayroon lamang isang limitasyon: ang suspend function ay maaari lamang tawagin mula sa coroutine o ibang suspend function.

Pangunahing deklarasyon

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

Sa halimbawang ito, ang delay ay isa ring suspend function na nagpapa-pause ng coroutine para sa tinukoy na bilang ng millisecond nang hindi hinaharangan ang thread. Pagkatapos ng pagkaantala, magpapatuloy ang pag-execute.

Pagtawag mula sa coroutine

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

Ang runBlocking ay lumilikha ng tulay sa pagitan ng ordinaryong mundo at mga coroutine. Sa loob ng lambda, pinapayagan ang pagtawag sa anumang suspend function.

Suspend lambda at functional na uri

Sinusuportahan ng Kotlin ang mga suspend na bersyon ng functional na uri — suspend () -> T at suspend (A) -> B. Ito ay nagpapahintulot sa pagpasa ng asynchronous lambda sa mga higher-order function:

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

Ang function na withRetry ay tumatanggap ng suspend lambda at inuulit ang pag-execute nito kapag may mga error. Ito ay tipikal na pattern para sa mga network request na may mga pagsubok muli.

Pagkakaiba ng mga suspend function sa ordinaryong function

Ang mga pagkakaiba sa pagitan ng suspend at ordinaryong function ay lampas sa simpleng pagdaragdag ng modifier. Tingnan natin ang mga pangunahing pagkakaiba.

KatangianOrdinaryong functionSuspend function
Thread ng pag-executeHinaharangan ang thread hanggang mataposMaaaring pakawalan ang thread at magpatuloy mamaya
Mga parameter ng compilerTanging tinukoy na mga parameterImplicit Continuation sa dulo
Pagtawag mula sa ordinaryong functionOoHindi
StackPisikal na stack ng threadState machine sa heap + pisikal na stack sa pagitan ng mga punto
ReturnDirektang halagaHalaga o COROUTINE_SUSPENDED
PagganapMinimal na overhead~ilang nanosecond para sa state machine (Kotlin 1.9+)

Bakit hindi maaaring tawagin ang mga suspend function mula sa ordinaryong function

Ang ordinaryong function ay walang Continuation — walang lugar upang i-save ang estado at ipagpatuloy ang pag-execute. Kung kailangan tumawag ng suspend function mula sa ordinaryong function, gamitin ang runBlocking (para sa pagsubok) o CoroutineScope.launch (para sa produksyon na isinasaalang-alang ang lifecycle).

Mga halimbawa ng suspend function sa Android

Tingnan natin ang tatlong totoong sitwasyon ng paggamit ng mga suspend function sa Android app na may Kotlin.

Halimbawa 1: Room DAO na may suspend query

Sinusuportahan ng Room ang mga suspend function nang direkta — ang query ay isinasagawa sa background nang awtomatiko:

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

    @Insert
    suspend fun insertUser(user: User)
}

Gumagamit ang Room sa loob ng Dispatchers.IO para isagawa ang query, at ang resulta ay ibinabalik sa dispatcher kung saan tinawag ang suspend function.

Halimbawa 2: Komposisyon ng mga suspend function para mag-load ng screen

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

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

Ang ViewModelScope.launch ay lumilikha ng coroutine, sa loob nito ay tinatawag ang suspend function na getProfile. Pagkatapos makuha ang resulta, ang UI ay ina-update sa pangunahing thread.

Halimbawa 3: Sunud-sunod na asynchronous na hakbang

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

Tatlong suspend function ang isinasagawa nang sunud-sunod. Sa bawat hakbang, ang coroutine ay maaaring huminto nang hindi hinaharangan ang thread. Kung ang isang hakbang ay nag-throw ng exception — ang iba ay hindi isinasagawa, na nagpoprotekta laban sa mga hindi wastong estado ng order.

Karaniwang pagkakamali sa paggamit ng mga suspend function

Kahit na ang mga may karanasang Kotlin developer ay nagkakamali sa pagdidisenyo ng mga suspend function. Tingnan natin ang pinakakaraniwan.

Pagkakamali 1: Mga panawag na humaharang sa loob ng suspend

Ang suspend function ay hindi ginagawang awtomatikong asynchronous ang code. Ang Thread.sleep(), InputStream.read(), at iba pang panawag na humaharang ay haharang pa rin sa thread. Gamitin ang withContext(Dispatchers.IO) para balutin ang mga operasyong humaharang.

Pagkakamali 2: Paggawa ng mga suspend function nang hindi kinakailangan

Kung ang isang function ay hindi tumatawag sa ibang suspend function at hindi gumaganap ng asynchronous operations — ang suspend modifier ay kalabisan. Nagdaragdag ito ng overhead sa state machine at nililimitahan ang konteksto ng pagtawag. Gawing suspend lamang ang function kapag ito ay talagang nagpa-pause.

Pagkakamali 3: Pagbalewala sa CancellationException

Kapag kinansela ang coroutine, ang mga suspend function ay nagh-throw ng CancellationException. Huwag itong hulihin nang walang pag-iisip — inaalis mo ang kakayahan ng tumatawag na code na wastong kumpletuhin ang pagkansela. Kung kailangan magsagawa ng finalizing operation, gamitin ang finally block at NonCancellable.

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

Ang finally block ay palaging isinasagawa, kabilang ang pagkansela, at ginagarantiyahan ng NonCancellable na ang paglilinis ay hindi mapuputol.

Pagkakamali 4: Pagtawag ng mga suspend function mula sa mga callback

Hindi maaaring tumawag ng suspend function nang direkta mula sa callback nang hindi gumagawa ng coroutine. Gamitin ang suspendCoroutine o suspendCancellableCoroutine para iakma ang callback style sa mga coroutine.

Mga Madalas Itanong

Maaari bang walang suspension point ang isang suspend function?

Oo, sa teknikal na paraan ang isang suspend function ay maaaring hindi tumawag ng ibang suspend function. Ang compiler ay gagawa ng state machine na may isang state (label 0). Gayunpaman, walang praktikal na pakinabang ang naturang function — ito ay isinasagawa tulad ng ordinaryong function, ngunit may overhead. Huwag gumamit ng suspend nang hindi kinakailangan.

Paano mag-debug ng mga suspend function?

Nagbibigay ang Kotlin ng kotlinx-coroutines-debug — isang library na may DebugProbes at mga tool sa pagsubaybay ng coroutine. Sa Android Studio simula sa bersyong Arctic Fox, mayroong built-in na Coroutines tab sa Debugger na nagpapakita ng mga aktibong coroutine, kanilang estado at mga suspension point.

Nakakaapekto ba ang bilang ng suspend point sa pagganap?

Bawat suspension point ay lumilikha ng bagong state sa state machine. Para sa karamihan ng mga application, ang overhead ng isang punto ay nasa yunit ng nanosecond (Kotlin 1.9+). Lamang kapag may sampu-sampung libong puntos sa isang loop, ito ay nagkakahalaga ng pagsasama-sama ng mga operasyon o paggamit ng sequence/flow.

Paano naiiba ang suspend function sa async/await sa ibang wika?

Sa Kotlin, ang suspend ay modifier ng uri ng function, hindi marker ng return value (tulad ng async sa C#). Anumang suspend function ay maaaring magkaroon ng anumang mga parameter at return type, at ang pagtawag nito ay syntactically hindi naiiba sa pagtawag ng ordinaryong function — walang await operator sa lugar ng pagtawag.

Paano i-convert ang callback function sa suspend?

Gamitin ang suspendCancellableCoroutine para sa adaptasyon. Sa loob, ipinapasa mo ang pagpaparehistro ng callback na tumatawag sa continuation.resume() at nagbabalik ng cancellation token kung sinusuportahan ng callback ang pag-unsubscribe. Ito ay karaniwang pattern para sa pagbalot ng lumang Android API.

Buod

  • Suspend function — function na may suspend modifier na maaaring mag-pause ng pag-execute nang hindi hinaharangan ang thread sa pamamagitan ng Continuation mechanism
  • State machine — panloob na representasyon ng suspend function sa Kotlin bytecode, kung saan ang bawat suspension point ay hiwalay na state na may label
  • Continuation — nakatagong parameter na naglalaman ng coroutine context at resumeWith method para magpatuloy ng pag-execute
  • Tawag lamang mula sa coroutine — ang mga suspend function ay hindi accessible mula sa ordinaryong function nang walang runBlocking o CoroutineScope
  • Mga operasyong humaharang sa loob ng suspend ay nangangailangan ng withContext(Dispatchers.IO) — kung hindi, ang thread ay haharangin
  • Room at Retrofit ay sumusuporta sa mga suspend function nang native, awtomatikong namamahala ng mga background thread
  • CancellationException — hawakan ang pagkansela sa pamamagitan ng finally + NonCancellable, huwag hulihin ang CancellationException nang walang pag-iisip

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din