---
title: "Kotlin Coroutines vs RxJava: Qual Melhor em 2026? | Kotlin Brasil"
url: "https://kotlin.dev.br/comparacoes/kotlin-coroutines-vs-rxjava/"
markdown_url: "https://kotlin.dev.br/comparacoes/kotlin-coroutines-vs-rxjava.MD"
description: "Comparação completa entre Kotlin Coroutines e RxJava. Performance, curva de aprendizado, casos de uso, exemplos de código e quando escolher cada um."
date: "2025-09-03"
author: "Karina Melo"
---

# Kotlin Coroutines vs RxJava: Qual Melhor em 2026? | Kotlin Brasil

Comparação completa entre Kotlin Coroutines e RxJava. Performance, curva de aprendizado, casos de uso, exemplos de código e quando escolher cada um.


## Kotlin Coroutines vs RxJava: programação assíncrona em 2026

A programação assíncrona e essencial no desenvolvimento moderno, seja para chamadas de rede, operações de banco de dados ou processamento em background. Durante anos, RxJava foi a solução dominante no ecossistema Android e JVM. Com a maturidade de Kotlin Coroutines e Flow, muitas equipes migraram ou consideram migrar. Este artigo compara as duas abordagens em profundidade.

## Visao geral

| Caracteristica | Kotlin Coroutines | RxJava |
|---------------|-------------------|--------|
| Linguagem | Kotlin nativo | Java (com extensoes Kotlin) |
| Paradigma | Suspensao sequencial | Streams reativos |
| Curva de aprendizado | Moderada | Alta |
| Backpressure | Flow (nativo) | Flowable (explicito) |
| Integração Android | Oficial (Jetpack) | Biblioteca terceira |
| Peso da dependência | Leve (~1.5MB) | Pesado (~3MB+) |
| Suporte multiplatform | Sim | Apenas JVM |
| Cancellamento | Estruturado (scope) | Manual (Disposable) |

## Modelo de programação

A diferenca fundamental esta na forma como cada abordagem expressa operações assíncronas.

### Coroutines: código sequencial com suspensao

Coroutines permitem escrever código assíncrono que parece sincrono. A palavra-chave `suspend` marca funções que podem pausar sem bloquear a thread:

```kotlin
// Coroutines: leitura natural, de cima para baixo
suspend fun buscarPerfilCompleto(userId: Int): PerfilCompleto {
    val usuario = api.buscarUsuario(userId)        // suspende
    val posts = api.buscarPosts(userId)             // suspende
    val seguidores = api.buscarSeguidores(userId)   // suspende
    return PerfilCompleto(usuario, posts, seguidores)
}

// Execução paralela quando necessario
suspend fun buscarPerfilParalelo(userId: Int): PerfilCompleto = coroutineScope {
    val usuario = async { api.buscarUsuario(userId) }
    val posts = async { api.buscarPosts(userId) }
    val seguidores = async { api.buscarSeguidores(userId) }
    PerfilCompleto(usuario.await(), posts.await(), seguidores.await())
}
```

### RxJava: cadeias de operadores reativos

RxJava modela tudo como streams de dados transformados por operadores:

```kotlin
// RxJava: cadeia de operadores
fun buscarPerfilCompleto(userId: Int): Single<PerfilCompleto> {
    return Single.zip(
        api.buscarUsuario(userId),
        api.buscarPosts(userId),
        api.buscarSeguidores(userId)
    ) { usuario, posts, seguidores ->
        PerfilCompleto(usuario, posts, seguidores)
    }
}

// Sequencial em RxJava
fun buscarPerfilSequencial(userId: Int): Single<PerfilCompleto> {
    return api.buscarUsuario(userId)
        .flatMap { usuario ->
            api.buscarPosts(userId).map { posts -> usuario to posts }
        }
        .flatMap { (usuario, posts) ->
            api.buscarSeguidores(userId).map { seguidores ->
                PerfilCompleto(usuario, posts, seguidores)
            }
        }
}
```

A versão com Coroutines e significativamente mais legivel. A versão RxJava requer conhecimento de operadores como `zip`, `flatMap` e `map` para expressar a mesma lógica.

## Tratamento de erros

### Coroutines: try/catch padrão

```kotlin
suspend fun carregarDados(): Resultado {
    return try {
        val dados = api.buscar()
        Resultado.Sucesso(dados)
    } catch (e: HttpException) {
        Resultado.Erro("Erro HTTP: ${e.code()}")
    } catch (e: IOException) {
        Resultado.Erro("Sem conexao")
    }
}
```

### RxJava: operadores de erro

```kotlin
fun carregarDados(): Single<Resultado> {
    return api.buscar()
        .map<Resultado> { dados -> Resultado.Sucesso(dados) }
        .onErrorReturn { e ->
            when (e) {
                is HttpException -> Resultado.Erro("Erro HTTP: ${e.code()}")
                is IOException -> Resultado.Erro("Sem conexao")
                else -> Resultado.Erro("Erro desconhecido")
            }
        }
}
```

O try/catch de Coroutines e familiar para qualquer desenvolvedor. Em RxJava, você precisa conhecer `onErrorReturn`, `onErrorResumeNext`, `retry` e outros operadores específicos para tratamento de erros.

## Cancelamento

### Coroutines: cancelamento estruturado

```kotlin
class MinhaViewModel : ViewModel() {
    // viewModelScope cancela automaticamente quando ViewModel e destruido
    fun carregarDados() {
        viewModelScope.launch {
            val dados = repositorio.buscar() // cancelado automaticamente
            _estado.value = dados
        }
    }
}

// Cancelamento manual
val job = scope.launch {
    while (isActive) {
        val dado = canal.receive()
        processar(dado)
    }
}
job.cancel() // cancela limpo
```

### RxJava: Disposable manual

```kotlin
class MinhaViewModel : ViewModel() {
    private val disposables = CompositeDisposable()

    fun carregarDados() {
        disposables.add(
            repositorio.buscar()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    { dados -> _estado.value = dados },
                    { erro -> _estado.value = Estado.Erro(erro) }
                )
        )
    }

    override fun onCleared() {
        disposables.clear() // esqueceu? vazamento de memoria
    }
}
```

O cancelamento estruturado de Coroutines e uma vantagem significativa. Com `viewModelScope`, `lifecycleScope` e coroutineScope, o cancelamento e automatico e hierarquico. Em RxJava, esquecer de chamar `dispose()` e uma fonte comum de bugs e vazamentos.

## Fluxos de dados reativos

### Kotlin Flow vs Observable/Flowable

```kotlin
// Kotlin Flow
fun observarUsuarios(): Flow<List<Usuario>> = flow {
    while (true) {
        val usuarios = api.buscarUsuarios()
        emit(usuarios)
        delay(30_000) // atualiza a cada 30 segundos
    }
}.catch { e ->
    emit(emptyList())
}.flowOn(Dispatchers.IO)

// Consumo
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.usuarios.collect { lista ->
            adapter.submitList(lista)
        }
    }
}
```

```kotlin
// RxJava Observable
fun observarUsuarios(): Observable<List<Usuario>> {
    return Observable.interval(0, 30, TimeUnit.SECONDS)
        .flatMapSingle { api.buscarUsuarios() }
        .onErrorReturnItem(emptyList())
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
}

// Consumo
disposables.add(
    viewModel.observarUsuarios()
        .subscribe { lista -> adapter.submitList(lista) }
)
```

### StateFlow vs BehaviorSubject

```kotlin
// Kotlin StateFlow
class ContadorViewModel : ViewModel() {
    private val _contador = MutableStateFlow(0)
    val contador: StateFlow<Int> = _contador.asStateFlow()

    fun incrementar() { _contador.value++ }
}

// RxJava BehaviorSubject
class ContadorViewModel : ViewModel() {
    private val _contador = BehaviorSubject.createDefault(0)
    val contador: Observable<Int> = _contador.hide()

    fun incrementar() { _contador.onNext(_contador.value!! + 1) }
}
```

## Performance

Em benchmarks práticos, Coroutines geralmente apresentam menor uso de memória e latencia comparable ou inferior a RxJava para a maioria dos cenários. A principal razao e que coroutines suspensas não alocam objetos intermediarios na mesma proporcao que cadeias de operadores RxJava.

| Metrica | Coroutines | RxJava |
|---------|-----------|--------|
| Memória por operação | Baixa (state machine) | Moderada (objetos Observable) |
| Overhead de criação | Minimo | Moderado (cadeia de operadores) |
| Troca de contexto | Eficiente (Dispatchers) | Schedulers (thread pool) |
| Cold start | Rapido | Mais lento (setup da cadeia) |

Para cenários com milhares de operações concorrentes, coroutines escalam melhor porque cada coroutine ocupa poucos bytes na memória, enquanto cada subscription RxJava mantém uma cadeia de objetos.

## Quando usar cada um

### Escolha Kotlin Coroutines quando:

- Você inicia um projeto novo em Kotlin
- Precisa de integração nativa com Jetpack (ViewModel, Room, Compose)
- Quer código mais legivel é fácil de depurar
- Precisa de suporte Kotlin Multiplatform
- A equipe tem experiência limitada com programação reativa
- Cancelamento automatico e importante

### Escolha RxJava quando:

- O projeto existente já usa RxJava extensivamente
- Você precisa de operadores complexos de combinacao de streams que não tem equivalente direto em Flow
- A equipe já domina o modelo reativo
- Você trabalha com um codebase Java que não pode migrar para Kotlin

### Migração gradual

Ambas as abordagens podem coexistir. A biblioteca `kotlinx-coroutines-rx3` oferece funções de conversao:

```kotlin
// RxJava para Flow
val flow: Flow<String> = observable.asFlow()

// Flow para Observable
val observable: Observable<String> = flow.asObservable()

// Single para suspend
val resultado: String = single.await()
```

## Veredito

Em 2026, Kotlin Coroutines com Flow e a escolha recomendada para novos projetos Kotlin. A integração com o ecossistema Android Jetpack e nativa, o modelo de cancelamento estruturado previne vazamentos, e o código resultante e mais legivel. RxJava permanece uma opção válida para projetos existentes que já investiram no modelo reativo, mas a tendencia clara do ecossistema e em direcao a Coroutines. Se você esta comecando hoje, invista seu tempo em dominar Coroutines e Flow. Para comparar modelos de concorrência além da JVM, veja como <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go implementa concorrência com goroutines e channels</a> e como <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust aborda async/await com segurança de memória garantida</a>.
