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 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.
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.
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.
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.
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:
Suponha que temos uma função suspend com duas chamadas a outras funções suspend:
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:
// 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.
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.
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.
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.
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:
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.
As diferenças entre funções suspend e comuns vão além de simplesmente adicionar um modificador. Vejamos as principais distinções.
| Característica | Função comum | Função suspend |
|---|---|---|
| Thread de execução | Bloqueia a thread até a conclusão | Pode liberar a thread e retomar depois |
| Parâmetros do compilador | Apenas parâmetros especificados | Continuation implícito no final |
| Chamada de função comum | Sim | Não |
| Pilha | Pilha física da thread | Máquina de estados no heap + pilha física entre pontos |
| Valor de retorno | Valor direto | Valor ou COROUTINE_SUSPENDED |
| Desempenho | Sobrecarga mínima | ~alguns nanossegundos por máquina de estados (Kotlin 1.9+) |
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).
Vejamos três cenários reais de uso de funções suspend em aplicativos Android com Kotlin.
Room suporta funções suspend diretamente — a consulta é executada em uma thread de fundo automaticamente:
@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.
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.
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.
Mesmo desenvolvedores Kotlin experientes cometem erros ao projetar funções suspend. Vejamos os mais comuns.
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.
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.
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.
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.
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
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.
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.
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.
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.
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
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.
Leia também