Comunicación Dentro de Una Aplicación Android Con EventBus
Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)
Una aplicación típica de Android tiende a estar compuesta de muchas capas, módulos o estructuras tales como Fragmentos, Actividades, Presentadores y Servicios. La comunicación efectiva entre estos componentes puede volverse difícil si están estrechamente emparejadas juntas.
En el nivel más bajo de la arquitectura de tu aplicación, como la base de datos, cuando una acción sucede, podrías querer enviar información a un nivel más alto como la vista. Para hacer esto, podrías querer crear una interfaz listener, tareas asíncronas o rellamados. Todos estos funcionarán, pero tienen algunos inconvenientes mayores:
- directo o emparejamiento estrecho
- registrando o quitando registro a múltiples dependencias individualmente
- repetición de código
- dificultad en pruebas
- riesgo incrementado de errores
Usar arquitectura publish/subscribe o bus de mensaje previene los problemas potenciales señalados arriba. Esta es una muy buena manera de implementar comunicaciones efectivas entre componentes en una aplicación si que ninguna de estas esté consciente de las otras inmediatamente. Usando publish/subscribe en Android, cualquier componente de aplicación puede publicar eventos que pasará al bus, y los consumidores relevantes pueden consumir o suscribirse a ellos.
Para usar greenrobot EventBus, primero necesitas agregarlo al archivo de módulo de app build.gradle, incluye compile 'org.greenrobot:eventbus:3.0.0', y después sincroniza tu proyecto.
Un Suscriptor de Evento
Un suscriptor simplemente se suscribe a un evento registrando en el bus de evento y también puede anular el registro de ese evento. Para ser un suscriptor, tienes que hacer tres cosas principales:
1. Registrar al suscriptor en el bus de evento con register(). Esto informa al evento que quieres comenzar a recibir eventos. En una actividad, esto es en el método onStart(), mientras en un fragmento pon esto en el método onAttact(Activity activity).
1 |
@Override
|
2 |
public void onStart() { |
3 |
super.onStart(); |
4 |
EventBus.getDefault().register(this); |
5 |
}
|
2. Anula el registro del suscriptor, lo cuál significa decirle al bus de evento que deje de enviarme eventos. En una actividad, esto es en el método onStop(), mientras que en un fragmento pon esto en el método onDetatch().
1 |
@Override
|
2 |
public void onStop() { |
3 |
super.onStop(); |
4 |
EventBus.getDefault().unregister(this); |
5 |
}
|
3. Implementa el onEvent() para indicar el tipo de evento que quieres recibir y la acción a tomar cuando recibes el evento. Nota la anotación @Subscribe al inicio de este método. En este caso, queremos suscribir a un evento normal y no a uno fijo--explicaré la diferencia más tarde.
1 |
@Subscribe
|
2 |
public void onEvent(MessageEvent event) { |
3 |
Toast.makeText(this, "Hey, my message" + event.getMessage(), Toast.LENGTH_SHORT).show();. |
4 |
}
|
Definiendo Mensajes de Eventos
Los eventos en greenbot EventBus son solo objetos que defines. Puedes tener diferentes clases de eventos si quieres. Ellos no heredan ninguna clase base o interfaz--son solo POJO (Plain Old Java Objects).
1 |
public class MessageEvent { |
2 |
|
3 |
public String mMessage; |
4 |
|
5 |
public MessageEvent(String message) { |
6 |
mMessage = message; |
7 |
}
|
8 |
|
9 |
public String getMessage() { |
10 |
return mMessage; |
11 |
}
|
12 |
}
|
Evento Post y Evento Fijo Post
La diferencia principal entre el evento post y el evento post fijo es el mecanismo de cacheo empleado dentro del bus de evento. Cuando alguien publica un evento fijo, este evento es almacenado en un caché. Cuando una nueva actividad o fragmento se suscribe al bus de evento, este obtiene el último evento fijo del caché en vez de esperar a que sea disparado otra vez al bus de evento--así que este evento se queda en el caché incluso después de que un suscriptor lo ha obtenido.
Los eventos fijos son publicados con el método postSticky(MessageEvent) y eventos no fijos con el método post(MessageEvent).
1 |
EventBus.getDefault().postSticky(new MessageEvent("Hey event subscriber!")); |
2 |
EventBus.getDefault().post(new MessageEvent("Hey event subscriber!")); |
Para un evento no fijo regular, si no se encuentra un suscriptor, el evento será deshechado. Un evento fijo será cacheado, sin embargo, en caso de que un suscriptor venga después.
¿Así que cuándo decides usar un evento fijo de publicación? Puedes hacer esto si estás dando seguimiento a la ubicación del usuario, o para un simple cacheo de datos, dar seguimiento a los niveles de la batería, etc.
1 |
EventBus.getDefault().postSticky(new LocationReceivedEvent(6.4531, 3.3958)) |
Suscribe a un Evento Fijo de Publicación
1 |
// UI updates must run on MainThread
|
2 |
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN) |
3 |
public void onEvent(MessageEvent event) { |
4 |
textField.setText(event.getMessage()); |
5 |
}
|
Para suscribir a un evento fijo, puedes incluir sticky = true dentro de la anotación @Subscribe. Esto indica que queremos recibir un evento fijo de tipo MessageEvent desde el caché.
Quitando Eventos Fijos
1 |
LocationReceivedEvent locationReceivedStickyEvent = EventBus.getDefault().getStickyEvent(LocationReceived.class); |
2 |
if(stickyEvent != null) { |
3 |
EventBus.getDefault().removeStickyEvent(locationReceivedStickyEvent); |
4 |
}
|
removeStickyEvent(Event) remueve un evento fijo del caché, y removeAllStickyEvents() removerá todos los eventos fijos.
Modos de Hilo EventBus
Hay cuatro modos de hilo disponibles de los cuales pueden elegir los suscriptores: publicación, principal, segundo plano, y asíncrono.
Publicación
1 |
@Subscribe(threadMode = ThreadMode.POSTING) |
Este es el valor por defecto. Los suscriptores serán llamados en el mismo hilo que el hilo en donde se publica el evento. Incluir ThreadMode.POSTING en tu anotación @Subscribe es opcional.
Principal
1 |
@Subscribe(threadMode = ThreadMode.MAIN) |
En este modo de hilo, los suscriptores recibirán eventos en el hilo UI principal, sin importar en donde haya sido publicado el evento. Este es el modo de hilo a usar si quieres actualizar elementos UI como resultado del evento.
Segundo Plano
1 |
@Subscribe(threadMode = ThreadMode.BACKGROUND) |
En este modo de hilo, los suscriptores recibirán eventos en el mismo hilo en donde fueron publicados, igual que para ThreadMode.POSTING. La diferencia es que si el evento es publicado en el hilo principal, entonces los suscriptores los obtendrán en un hilo en segundo plano en su lugar. Esto asegura que el manejo del evento no bloquee la UI de la app. Aún así, no ejecutes una operación que llevará un largo tiempo en este hilo.
Asíncrono
1 |
@Subscribe(threadMode = ThreadMode.ASYNC) |
En este modo de hilo, los suscriptores siempre recibirán eventos independientemente del hilo actual y principal. Esto permite a los suscriptores ejecutarse en un hilo separado. Esto es útil para operaciones a largo plazo tales como operaciones de red.
Prioridades de Suscriptor
Si quieres cambiar el orden en el cuál los suscriptores reciben eventos, entonces necesitas especificar sus niveles de prioridad durante el registro. Los suscriptores con una prioridad más alta reciben el evento antes que suscriptores con una prioridad más baja. Esto solo afecta a suscriptores en el mismo modo de hilo. Nota que la prioridad por defecto es 0.
1 |
@Subscribe(priority = 1); |
2 |
public void onEvent(MessageEvent event) { |
3 |
textField.setText(event.getMessage()); |
4 |
}
|
Cancelando Eventos
Si quieres detener un evento de ser entregado a otros suscriptores, llama al método cancelEventDelivery(Object event) dentro del método de manejo del evento del suscriptor.
1 |
@Subscribe
|
2 |
public void onEvent(MessageEvent event){ |
3 |
EventBus.getDefault().cancelEventDelivery(event); |
4 |
}
|
Conclusión
En este tutorial, aprendiste sobre:
- greenrobot EventBus y cómo puede mejorar tu app Android
- la diferencia entre eventos regulares y fijos
- los distintos modos de hilos disponibles y cuándo usar cada uno
- prioridades de suscriptor
- cancelar un evento para dejar de recibir eventos
Para aprender más sobre greenrobot EventBus, te sugiero visitar la documentación oficial.
Otra librería que puedes usar para implementar un bus de evento es RxAndroid. Revisa nuestro artículo RxAndroid aquí en Envato Tuts+, o prueba algunos de nuestros otros cursos o tutoriales Android.











