Event Bus e padrão Observer em Kotlin: guia completo
No desenvolvimento moderno de aplicações em Kotlin (especialmente para Android), surge frequentemente a necessidade de organizar uma interação fracamente acoplada entre componentes. O padrão Observer e sua implementação prática — Event Bus — fornecem uma solução elegante para essa tarefa. Neste artigo, vamos detalhar o que é Event Bus, como funciona o padrão Observer e como aplicar esses conceitos em projetos Kotlin.
O que é o padrão Observer?
O padrão Observer (Observador) é um padrão de design comportamental no qual um objeto (sujeito) notifica vários outros objetos (observadores) sobre mudanças em seu estado. Componentes principais:
- Subject — editor de eventos que mantém uma lista de assinantes.
- Observer — assinante que recebe notificações.
- Event — mensagem ou dados específicos transmitidos do editor para os assinantes.
Event Bus como implementação do Observer
Event Bus (barramento de eventos) é um mecanismo centralizado que simplifica o uso do padrão Observer. Em vez de cada sujeito gerenciar manualmente sua lista de observadores, o Event Bus assume toda a lógica de assinatura, cancelamento e entrega de eventos. Isso é especialmente útil em aplicações com arquitetura complexa, onde os componentes não devem saber diretamente uns dos outros.
Vantagens do Event Bus em Kotlin
- Baixo acoplamento — os componentes se comunicam através do barramento, sem ter referências diretas uns aos outros.
- Facilidade de teste — é possível simular facilmente o barramento de eventos.
- Flexibilidade — é fácil adicionar novos assinantes sem alterar o código existente.
- Assincronicidade — os eventos podem ser processados em diferentes threads.
Implementação simples de Event Bus em Kotlin
Vamos criar nossa própria implementação simples de Event Bus sem bibliotecas externas. Isso ajudará a entender a mecânica interna do funcionamento.
import kotlin.reflect.KClass
class EventBus { private val subscribers = mutableMapOf<KClass<*>, MutableList<(Any) -> Unit>>()
// Assinar um evento de um tipo específico inline fun <reified T : Any> subscribe(crossinline onEvent: (T) -> Unit) { val eventType = T::class subscribers.getOrPut(eventType) { mutableListOf() }.add { event -> if (event is T) { onEvent(event) } } }
// Cancelar assinatura de todos os eventos (para demonstração) fun <T : Any> unsubscribe(eventType: KClass<T>) { subscribers.remove(eventType) }
// Publicar um evento fun publish(event: Any) { val eventType = event::class subscribers[eventType]?.forEach { handler -> handler(event) } }}
// Exemplo de usodata class UserLoggedIn(val userId: String, val timestamp: Long)data class DataLoaded(val data: String)
fun main() { val bus = EventBus()
// Assinamos o evento de login do usuário bus.subscribe<UserLoggedIn> { event -> println("Usuário ${event.userId} fez login em ${event.timestamp}") }
// Assinamos o evento de carregamento de dados bus.subscribe<DataLoaded> { event -> println("Dados carregados: ${event.data}") }
// Publicamos os eventos bus.publish(UserLoggedIn("user123", System.currentTimeMillis())) bus.publish(DataLoaded("Exemplo de dados"))}Biblioteca pronta: GreenRobot EventBus
Em projetos reais, é mais comum usar bibliotecas prontas. Uma das mais populares para Kotlin/Android é o GreenRobot EventBus. Ela é otimizada para funcionar com componentes Android e suporta:
Também na biblioteca
gomail
Cliente Elasticsearch para Kotlin: integração, exemplos e recursos