EventBus: o que é, princípio de funcionamento e barramento de eventos Android

Autor: IT Sectr Publicado: 2026-03-18 Tempo de leitura: 10 min

EventBus é uma biblioteca para Android que implementa o padrão Publisher-Subscriber através de um barramento de eventos, permitindo a troca de dados entre componentes sem dependências diretas. Desenvolvida pela GreenRobot, a biblioteca simplifica a comunicação entre Activity, Fragment, Service e Background Thread. De acordo com dados do GitHub (2025), o EventBus tem mais de 25 mil estrelas e é usado em milhares de aplicativos Android. As principais operações são subscribe (inscrição em um evento), post (envio de um evento) e sticky event (evento adiado para novos assinantes).

Pontos principais

  • EventBus é uma biblioteca de barramento de eventos para comunicação fracamente acoplada no Android.
  • @Subscribe é uma anotação que marca um método como manipulador de um tipo de evento específico.
  • EventBus.getDefault().post() envia um evento para todos os manipuladores inscritos.
  • Sticky event mantém o último evento para entrega a novos assinantes.
  • ThreadMode determina a thread de execução do manipulador: MAIN, POSTING, BACKGROUND, ASYNC.

O que é EventBus?

EventBus é uma biblioteca de barramento de eventos para Android que implementa o padrão Publisher-Subscriber. Ela permite passar eventos entre componentes do aplicativo (Activity, Fragment, Service, ViewModel) sem criar dependências explícitas entre eles. Ao contrário dos mecanismos padrão do Android (Intent, BroadcastReceiver), o EventBus funciona dentro do processo e não usa IPC. A biblioteca é otimizada para desempenho e não usa reflexão quando o Subscriber Index está configurado corretamente.

GreenRobot EventBus: arquitetura

A arquitetura do EventBus consiste em três elementos-chave: Event (classe POJO com dados), Subscriber (objeto com métodos anotados com @Subscribe) e EventBus (despachante central). O assinante se registra através de EventBus.getDefault().register(this) e cancela o registro através de unregister(this). Os eventos são tipados: os manipuladores se inscrevem em uma classe de evento específica e são invocados apenas quando um evento dessa classe ou suas subclasses é postado.

kotlin
// Evento POJO
data class MessageEvent(
    val message: String,
    val timestamp: Long = System.currentTimeMillis()
)

// Assinante em Activity
class MainActivity : AppCompatActivity() {

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        EventBus.getDefault().unregister(this)
        super.onStop()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMessageEvent(event: MessageEvent) {
        textView.text = event.message
    }
}

// Envio de evento de outro componente
EventBus.getDefault().post(MessageEvent("Hello from Service"))

Subscriber Index para desempenho

Por padrão, o EventBus usa reflexão para encontrar métodos @Subscribe durante register(). Subscriber Index gera um índice de manipuladores em tempo de compilação através de um processador de anotações. Isso elimina a sobrecarga da reflexão e acelera o registro. Para ativar, adicione eventbus-annotation-processor ao build.gradle. O EventBus usa o índice automaticamente se estiver disponível no classpath. Sem o índice, a biblioteca ainda funciona, mas com uma ligeira diminuição no desempenho.

Como o EventBus funciona no Android?

Quando EventBus.getDefault().post(event) é chamado, a biblioteca determina o tipo de evento, encontra todos os assinantes registrados com métodos @Subscribe que aceitam esse tipo e os invoca de acordo com o ThreadMode especificado. A busca por assinantes é realizada usando um mapa Class → CopyOnWriteArrayList construído durante o registro. Se um evento não tiver assinantes, post é concluído sem erro — este é um comportamento safe-fail.

Ciclo de vida do registro

Um assinante deve registrar-se em onStart() e cancelar o registro em onStop(). Se você registrar em onCreate() e cancelar em onDestroy(), uma Activity destruída sem chamar onDestroy (devido a finish()) pode permanecer na lista de assinantes. Vazamento de assinante é um dos principais problemas do EventBus: uma Activity que permanece na lista de assinantes não será coletada pelo GC até cancelar o registro. Sempre emparelhe register/unregister nos métodos de ciclo de vida corretos.

Prioridade de manipuladores

A anotação @Subscribe suporta um parâmetro priority (inteiro, padrão 0). Manipuladores com prioridade mais alta são chamados primeiro. cancelEventDelivery() permite interromper a entrega do evento aos assinantes restantes. Isso é útil para manipuladores prioritários (logging, autenticação) que podem cancelar o processamento do evento por assinantes downstream. Esta função está disponível apenas na thread de postagem do evento.

kotlin
// Exemplo complexo com prioridade
data class NavigationEvent(val screen: String, val data: Bundle)

class NavigationInterceptor {
    @Subscribe(priority = 10, threadMode = ThreadMode.POSTING)
    fun onNavigationEvent(event: NavigationEvent) {
        if (event.screen == "restricted" && !isAuthorized) {
            EventBus.getDefault().cancelEventDelivery(event)
        }
    }
}

class AnalyticsLogger {
    @Subscribe(priority = 5)
    fun logNavigation(event: NavigationEvent) {
        analytics.logScreen(event.screen)
    }
}

// Envio de evento
EventBus.getDefault().post(NavigationEvent("profile", bundle))

EventBus vs LocalBroadcastManager vs LiveData

O Android oferece vários mecanismos para comunicação intra-processo: EventBus, LocalBroadcastManager (obsoleto) e LiveData/Flow. Cada um tem suas vantagens e desvantagens. A escolha depende da abordagem arquitetônica e dos requisitos de desempenho. As recomendações modernas do Google se inclinam para LiveData e Flow devido à integração com Lifecycle e à ausência de vazamentos.

CaracterísticaEventBusLocalBroadcastManagerLiveData / Flow
TipagemVia classe de eventoVia filtro Intent (String)Via tipo genérico
Lifecycle-awareNão (cancelamento manual)Não (cancelamento manual)Sim (automático)
StickySim (postSticky)NãoSim (LiveData é sempre sticky)
ThreadModeMAIN, POSTING, BACKGROUND, ASYNCApenas mainVia observe/observeOn
DesempenhoAlto (Subscriber Index)Médio (wrapper IPC)Alto (observação)

Quando o EventBus é preferível

O EventBus é útil em projetos com código legado significativo e onde LiveData/Flow não estão disponíveis (projetos apenas Java). Os sticky events do EventBus oferecem flexibilidade ausente no LocalBroadcastManager. O EventBus também é mais fácil para enviar eventos de Service para Activity sem ViewModel — especialmente quando você precisa notificar sobre o progresso de uma tarefa em segundo plano. A biblioteca tem tamanho mínimo (cerca de 50 KB) e não adiciona dependências.

Quando LiveData/Flow é preferível

LiveData e Flow fazem parte do Android Jetpack e são integrados ao Lifecycle. Eles cancelam a inscrição automaticamente quando um componente é destruído, eliminando vazamentos de memória. O Flow suporta corrotinas e operadores de transformação complexos. O Google recomenda LiveData para a camada de UI e Flow para repositórios. O EventBus permanece útil para eventos entre módulos onde a navegação e a lógica de negócios não se encaixam no MVVM.

Subscribe e Post: operações básicas

Subscribe é o registro de um manipulador de eventos através da anotação @Subscribe. O método deve ser public, void e aceitar exatamente um parâmetro — o tipo de evento. Post é o envio de um evento para todos os manipuladores inscritos através de EventBus.getDefault().post(event). O método post não retorna um resultado nem indica quantos manipuladores foram invocados. Para eventos com resposta, use uma classe Event separada com um campo de resultado.

Criação de eventos personalizados

Um evento é qualquer classe Java/Kotlin. Recomenda-se usar data class para eventos imutáveis e uma classe normal para eventos com campos mutáveis. A nomenclatura do evento deve refletir a ação: UserLoggedInEvent, DataLoadedEvent, NetworkErrorEvent. Evite uma única classe Event genérica com um campo String type — isso elimina os benefícios da tipagem. Uma hierarquia de eventos (Event pai) permite inscrever-se em um grupo de eventos relacionados.

kotlin
// Hierarquia de eventos
open class UserEvent
data class UserLoggedIn(val userId: String) : UserEvent()
data class UserLoggedOut(val reason: String) : UserEvent()

// Inscrição na classe base
class SessionManager {
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onUserEvent(event: UserEvent) {
        when (event) {
            is UserLoggedIn -> startSession(event.userId)
            is UserLoggedOut -> endSession(event.reason)
        }
    }
}

// Envio
EventBus.getDefault().post(UserLoggedIn("user_123"))

Registro e cancelamento de registro

Chamar EventBus.getDefault().register(this) escaneia a classe do assinante através de reflexão ou Subscriber Index e armazena os métodos @Subscribe encontrados no mapa de eventos. Unregister remove o assinante do mapa. O re-registro sem cancelamento é um erro (lançará MultipleSubscriberException). Para Fragment, registre-se em onStart() e cancele em onStop(). Para Service, em onCreate() e onDestroy(). Para ViewModel, não é recomendado — use LiveData.

Sticky Events e ThreadMode

Um sticky event é um evento que persiste no EventBus após ser enviado. Novos assinantes registrados após postSticky() recebem imediatamente o último sticky event do tipo correspondente. Isso é conveniente para passar o estado inicial: ao abrir uma tela, ela recebe os dados mais recentes enviados antes de seu registro. Você pode remover um sticky event através de EventBus.getDefault().removeStickyEvent(Class).

ThreadMode: quatro modos de execução

ThreadMode determina em qual thread o manipulador é executado. POSTING (padrão) — o manipulador executa na mesma thread onde post foi chamado. MAIN — o manipulador executa na main thread através de Handler. BACKGROUND — o manipulador executa em uma thread em segundo plano; se post foi chamado na main thread, o EventBus coloca o manipulador em uma fila de thread em segundo plano. ASYNC — cada manipulador executa em uma thread em segundo plano separada de um pool de threads. Para atualizações de UI, use MAIN.

kotlin
// Sticky Event
data class LocationEvent(val lat: Double, val lng: Double)

// Envio de sticky event do LocationService
EventBus.getDefault().postSticky(LocationEvent(55.7558, 37.6173))

// Assinante recebe a última localização imediatamente após o registro
class MapFragment : Fragment() {
    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
        // Receberá imediatamente LocationEvent se postSticky foi chamado
    }

    override fun onStop() {
        EventBus.getDefault().unregister(this)
        super.onStop()
    }

    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
    fun onLocationEvent(event: LocationEvent) {
        moveMapTo(event.lat, event.lng)
    }
}

// Remoção de sticky event
EventBus.getDefault().removeStickyEvent(LocationEvent::class.java)

ThreadMode.BACKGROUND vs ASYNC

BACKGROUND usa uma única thread em segundo plano para todos os manipuladores — eles executam sequencialmente. ASYNC cria uma nova thread do pool para cada manipulador — eles executam em paralelo. BACKGROUND é adequado para operações de E/S com um banco de dados compartilhado. ASYNC é para operações longas independentes (solicitações de rede). Ambos os modos exigem acesso thread-safe a recursos compartilhados. Lembre-se do número de threads: o pool ASYNC é ilimitado.

Erros comuns e desempenho do EventBus

Ao usar o EventBus, os desenvolvedores frequentemente cometem erros que levam a vazamentos de memória, invocações inesperadas e degradação do desempenho. Os mais críticos: esquecer o cancelamento do registro em Activity, registrar em onCreate (em vez de onStart/onStop), inscrever-se em Object (todos os eventos), enviar eventos em um loop infinito. A criação de perfil com Android Profiler ajuda a identificar problemas.

Vazamentos de memória através do EventBus

O erro mais comum é registrar uma Activity em onCreate() sem cancelar o registro em onDestroy(). Resultado: o EventBus mantém uma referência à Activity, o GC não pode liberá-la. Ao girar a tela, uma nova Activity é criada enquanto a anterior permanece na memória. Solução: sempre emparelhe register/unregister em onStart/onStop. Para Fragment, use o mesmo padrão. Se uma Activity for retida pelo EventBus após finish, verifique com Memory Profiler.

Desempenho: Subscriber Index

Sem Subscriber Index, o EventBus usa reflexão para encontrar métodos @Subscribe em cada register(). Em dispositivos com Android 6-7, a reflexão é lenta, causando atrasos de até 50 ms. O Subscriber Index elimina a reflexão completamente: os métodos são indexados em tempo de compilação através de um processador de anotações. Para projetos com 20 ou mais assinantes, o índice é obrigatório. Certifique-se de que kapt ou annotationProcessor está configurado no build.gradle.

groovy
// build.gradle (app) — adicionar Subscriber Index
dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}

// Para Kotlin use kapt
plugins {
    id 'kotlin-kapt'
}

dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
    kapt 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}

// Configuração do índice (em defaultConfig)
kapt {
    arguments {
        arg('eventBusIndex', 'com.app.EventBusIndex')
    }
}

Alternativas ao EventBus no Android moderno

Projetos modernos usando Kotlin e Jetpack Compose preferem SharedFlow e Channel da biblioteca kotlinx.coroutines. O SharedFlow suporta replay (sticky), buffering e backpressure. O Channel lida com eventos únicos (toast, navegação). Ambas as soluções são integradas ao Lifecycle através de repeatOnLifecycle e não requerem cancelamento manual de inscrição. Para novos projetos, o SharedFlow é recomendado em vez do EventBus. Para projetos existentes, a migração é justificada durante a refatoração.

Perguntas frequentes

Qual é a diferença entre EventBus e LiveData?

EventBus é um barramento de eventos para troca de dados entre quaisquer componentes (Activity, Fragment, Service). LiveData é um wrapper lifecycle-aware para dados observados por um componente de UI. O LiveData gerencia automaticamente a inscrição através do Lifecycle. O EventBus requer register/unregister manual. O LiveData é recomendado para a camada de UI, o EventBus para comunicação entre módulos onde o LiveData é inconveniente.

O que é um sticky event?

Um sticky event é um evento que persiste no EventBus após ser enviado. Novos assinantes registrados após postSticky() recebem imediatamente o último sticky event. É usado para estado inicial: ao abrir uma tela, ela recebe os dados mais recentes sem uma nova solicitação. É removido via removeStickyEvent() ou quando um novo sticky event do mesmo tipo é enviado.

O EventBus é thread-safe?

Sim, o EventBus é thread-safe. Chamar post() é possível de qualquer thread. A entrega de eventos aos assinantes é sincronizada internamente. O ThreadMode determina a thread de execução do manipulador: MAIN (main thread via Handler), POSTING (thread da chamada), BACKGROUND (fila de tarefas em segundo plano), ASYNC (thread separada). Para atualizações de UI, use MAIN. Para operações pesadas, use ASYNC.

Como depurar o EventBus?

Ative o registro através de EventBus.builder().logNoSubscriberMessages(true).sendNoSubscriberEvent(true).install(). Inscreva-se em NoSubscriberEvent para rastrear eventos sem manipuladores. Use SubscriberExceptionEvent para tratamento global de exceções. O Android Profiler ajuda a encontrar vazamentos. Para cenários complexos, escreva um teste: EventBus.getDefault().register(mock) + post(event) + verify(mock).

O EventBus pode ser usado no Kotlin Multiplatform?

Não, o EventBus (GreenRobot) está vinculado ao Android SDK e JVM. Para Kotlin Multiplatform, use Kotlin Multiplatform SharedFlow ou KMMBus — bibliotecas que suportam código compartilhado. O EventBus funciona no lado Android de um projeto KMM, mas não está disponível no commonMain. Para eventos entre plataformas, prefira mecanismos nativos da plataforma ou abstração através de expect/actual.

Resumo

  • EventBus é uma biblioteca Publisher-Subscriber para Android que implementa um barramento de eventos com tipagem através de classes POJO.
  • A anotação @Subscribe com parâmetros threadMode, sticky, priority define o comportamento do manipulador de eventos.
  • post() envia um evento para todos os assinantes de forma síncrona; postSticky() retém o evento para novos assinantes.
  • ThreadMode controla a thread de execução: POSTING (thread da chamada), MAIN (UI), BACKGROUND (fila), ASYNC (pool).
  • Subscriber Index através do processador de anotações elimina a reflexão e acelera o registro.
  • Vazamentos de memória são prevenidos com register/unregister emparelhados em onStart/onStop de Activity ou Fragment.
  • Para novos projetos, SharedFlow/Channel do kotlinx.coroutines são preferíveis — são lifecycle-aware e thread-safe.

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