suspend function: o que é, sintaxe e funcionamento em corrotinas

Autor: IT Sectr Publicado: 2026-06-22 Tempo de leitura: 9 min

Suspend function é uma função com o modificador suspend que pode pausar sua execução sem bloquear uma thread e retomar mais tarde na mesma corrotina. De acordo com JetBrains Kotlin Docs, 2025, funções suspend são um bloco fundamental das corrotinas, fornecendo assincronia sem callbacks. Cada função suspend é compilada em uma máquina de estados baseada em Continuation, permitindo gerenciamento eficiente dos pontos de suspensão.

Pontos principais

  • Suspend — palavra-chave Kotlin que marca uma função como pausável (assíncrona)
  • Continuation — parâmetro oculto que o compilador adiciona a cada função suspend para salvar o estado
  • Pontos de suspensão — locais onde outras funções suspend são chamadas, onde uma corrotina pode parar sem bloquear
  • Máquina de estados — representação interna de uma função suspend, onde cada ponto de suspensão é um estado separado
  • Chamada apenas de corrotina — funções suspend só podem ser chamadas de outra função suspend ou de launch/async

O que é uma suspend function em Kotlin?

Suspend function é uma função declarada com a palavra-chave suspend que pode pausar a execução em um ou mais pontos sem bloquear a thread. Cada chamada a uma função suspend dentro de outra função suspend é um ponto de suspensão potencial.

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

O compilador Kotlin traduz essa função em uma máquina de estados. Cada ponto de suspensão (uma chamada a outra função suspend) torna-se um estado (label). A thread atual é liberada entre os estados e, quando a operação aguardada é concluída, a execução é retomada a partir do próximo estado.

História

As funções suspend apareceram no Kotlin 1.3 (2018) junto com as corrotinas como um recurso experimental e tornaram-se estáveis no Kotlin 1.5 (2021). Antes disso, a assincronia em Kotlin/Java era alcançada por meio de callbacks, RxJava e CompletableFuture. As funções suspend ofereceram uma alternativa com sintaxe linear e gerenciamento automático de threads.

Como funcionam as funções suspend: Continuation e máquina de estados

Entender o funcionamento interno das funções suspend é a chave para trabalhar corretamente com corrotinas. Diferentemente das funções comuns, cada função suspend é compilada em uma classe com a interface Continuation.

Continuation — o parâmetro oculto

O compilador Kotlin adiciona um parâmetro do tipo Continuation ao final de cada lista de parâmetros de uma função suspend. Continuation contém:

  • context — CoroutineContext (dispatcher, job, elementos do contexto)
  • resumeWith — método para retomar a execução com um resultado ou exceção
  • label — índice do estado atual na máquina de estados

Exemplo de máquina de estados

Suponha que temos uma função suspend com duas chamadas a outras funções suspend:

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

O compilador a transforma em uma máquina de estados com rótulos:

kotlin
// Simplified generated code representation
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
        }
    }
}

Observação chave: se a função retornar COROUTINE_SUSPENDED, a thread atual é liberada. Quando a operação assíncrona é concluída, Continuation.resumeWith é chamado e a máquina de estados continua a partir do próximo rótulo.

Sintaxe de funções suspend: declaração e invocação

Declarar uma função suspend não é diferente de uma função comum, exceto pela palavra-chave suspend antes de fun. Há apenas uma restrição: uma função suspend só pode ser chamada de uma corrotina ou de outra função suspend.

Declaração básica

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

Neste exemplo, delay também é uma função suspend que suspende a corrotina pelo número especificado de milissegundos sem bloquear a thread. Após o atraso, a execução é retomada.

Chamada de uma corrotina

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

runBlocking cria uma ponte entre o mundo comum e as corrotinas. Dentro da lambda, qualquer função suspend pode ser chamada.

Lambdas suspend e tipos funcionais

Kotlin suporta versões suspend de tipos funcionais — suspend () -> T e suspend (A) -> B. Isso permite passar lambdas assíncronas para funções de ordem superior:

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

A função withRetry recebe uma lambda suspend e tenta novamente sua execução em caso de erro. Este é um padrão típico para requisições de rede com tentativas.

Diferenças entre funções suspend e funções comuns

As diferenças entre funções suspend e comuns vão além de simplesmente adicionar um modificador. Vejamos as principais distinções.

CaracterísticaFunção comumFunção suspend
Thread de execuçãoBloqueia a thread até a conclusãoPode liberar a thread e retomar depois
Parâmetros do compiladorApenas parâmetros especificadosContinuation implícito no final
Chamada de função comumSimNão
PilhaPilha física da threadMáquina de estados no heap + pilha física entre pontos
Valor de retornoValor diretoValor ou COROUTINE_SUSPENDED
DesempenhoSobrecarga mínima~alguns nanossegundos por máquina de estados (Kotlin 1.9+)

Por que funções suspend não podem ser chamadas de funções comuns

Uma função comum não tem um Continuation — ela não tem onde salvar o estado nem com o que retomar a execução. Se precisar chamar uma função suspend de uma função comum, use runBlocking (para testes) ou CoroutineScope.launch (para produção com ciência do ciclo de vida).

Exemplos de funções suspend no Android

Vejamos três cenários reais de uso de funções suspend em aplicativos Android com Kotlin.

Exemplo 1: Room DAO com consultas suspend

Room suporta funções suspend diretamente — a consulta é executada em uma thread de fundo automaticamente:

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

    @Insert
    suspend fun insertUser(user: User)
}

Room usa internamente Dispatchers.IO para executar a consulta, e o resultado é retornado no dispatcher onde a função suspend foi chamada.

Exemplo 2: Composição de funções suspend para carregamento de tela

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

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

ViewModelScope.launch cria uma corrotina, dentro da qual a função suspend getProfile é chamada. Após obter o resultado, a UI é atualizada na thread principal.

Exemplo 3: Passos assíncronos sequenciais

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

Três funções suspend são executadas sequencialmente. Em cada passo, a corrotina pode suspender sem bloquear a thread. Se algum passo lançar uma exceção, os passos restantes não são executados, protegendo contra estados de pedido incorretos.

Erros comuns ao trabalhar com funções suspend

Mesmo desenvolvedores Kotlin experientes cometem erros ao projetar funções suspend. Vejamos os mais comuns.

Erro 1: Chamadas bloqueantes dentro de suspend

Uma função suspend não torna o código automaticamente assíncrono. Thread.sleep(), InputStream.read() e outras chamadas bloqueantes ainda bloquearão a thread. Use withContext(Dispatchers.IO) para envolver operações bloqueantes.

Erro 2: Criar funções suspend sem necessidade

Se uma função não chama outras funções suspend e não realiza operações assíncronas — o modificador suspend é redundante. Ele adiciona sobrecarga à máquina de estados e restringe o contexto de chamada. Torne uma função suspend apenas quando ela realmente suspende.

Erro 3: Ignorar CancellationException

Quando uma corrotina é cancelada, funções suspend lançam CancellationException. Não a capture sem pensar — você priva o código chamador da capacidade de completar corretamente o cancelamento. Se precisar realizar uma operação de finalização, use um bloco finally e NonCancellable.

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

O bloco finally sempre executa, inclusive no cancelamento, e NonCancellable garante que a limpeza não seja interrompida.

Erro 4: Chamar funções suspend de callbacks

Você não pode chamar uma função suspend diretamente de um callback sem criar uma corrotina. Use suspendCoroutine ou suspendCancellableCoroutine para adaptar o estilo de callback às corrotinas.

Perguntas frequentes

Uma função suspend pode não ter pontos de suspensão?

Sim, tecnicamente uma função suspend pode não chamar outras funções suspend. O compilador criará uma máquina de estados com um único estado (label 0). No entanto, não há benefício prático em tal função — ela executa como uma comum mas com sobrecarga. Não use suspend desnecessariamente.

Como depurar funções suspend?

Kotlin fornece kotlinx-coroutines-debug — uma biblioteca com DebugProbes e ferramentas de rastreamento de corrotinas. No Android Studio a partir do Arctic Fox, há uma guia Coroutines integrada no Depurador que mostra corrotinas ativas, seu estado e pontos de suspensão.

O número de pontos de suspensão afeta o desempenho?

Cada ponto de suspensão cria um novo estado na máquina de estados. Para a maioria das aplicações, a sobrecarga de um ponto é de alguns nanossegundos (Kotlin 1.9+). Apenas com dezenas de milhares de pontos em um loop você deve considerar combinar operações ou usar sequence/flow.

Como uma função suspend difere de async/await em outras linguagens?

Em Kotlin, suspend é um modificador de tipo de função, não um marcador de valor de retorno (como async em C#). Qualquer função suspend pode ter quaisquer parâmetros e tipo de retorno, e sua chamada sintaticamente não difere de uma chamada de função comum — não há operador await no local da chamada.

Como converter uma função callback para suspend?

Use suspendCancellableCoroutine para adaptação. Internamente, você registra um callback que chama continuation.resume(), e retorna um token de cancelamento se o callback suportar cancelamento de inscrição. Este é o padrão padrão para envolver APIs antigas do Android.

Resumo

  • Suspend function — função com o modificador suspend que pode pausar a execução sem bloquear uma thread através do mecanismo Continuation
  • Máquina de estados — representação interna de uma função suspend em bytecode Kotlin, onde cada ponto de suspensão é um estado separado com um rótulo
  • Continuation — parâmetro oculto contendo o contexto da corrotina e o método resumeWith para retomar a execução
  • Chamada apenas de corrotina — funções suspend não são acessíveis de funções comuns sem runBlocking ou CoroutineScope
  • Operações bloqueantes dentro de suspend requerem withContext(Dispatchers.IO) — caso contrário a thread bloqueia
  • Room e Retrofit suportam funções suspend nativamente, gerenciando automaticamente threads de fundo
  • CancellationException — lide com cancelamento via finally + NonCancellable, não capture CancellationException sem pensar

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também