Chapter 11. Exploring Bus-based Communications
In previous chapters, we have been using different techniques to disseminate data/events/notifications between several Android application components (Activity
, Fragment
, Service
, BroadcastReceiver, …
):
Intents were sent through the system carrying communication messages or notifications to notify a Service
or Activity
to start
Broadcast Intents were used to report a result back from background processes
Handlers were used to communicate between different processes and thread executions
These techniques usually involved a tight coupling between the component that sends the message and the component that receives it. Typically, the sender dispatches a message to a certain receiver and deals with the receiver lifecycle in order to detect any receiver unavailability.
In this chapter, we are going to present to the reader a new construct and pattern, delivered by the EventBus
library, that most of the time simplifies communication between the different...
Introduction to bus-based communication
The Bus based communication software pattern, also known as Publish/Subscribe, is a pattern that allows sender and receiver entities to communicate without requiring them to explicitly know each other. This communication model suppresses the tight coupling between components and allows the delivery of messages from one receiver to more than one final recipient. There are five different entities involved in the communication pattern: publisher, subscriber, event, bus, and broker.
The publisher submits events to a shared messaging pipeline, named bus, controlled by an entity called broker, that governs the stream of events submitted and forwards them to a list of interested entities, called subscribers, that previously registered in the broker to receive certain kinds of event.
In order to receive certain kinds of event, the subscriber should express interest in these events by creating a subscription in the broker and the broker should keep a list of...
Although there are several open source libraries that are able to deliver this kind of pattern in Android, we will base our code examples on the popular event bus library (http://greenrobot.org/eventbus/) since it offers advanced features and high performance.
The high performance library is optimized for the Android OS and it has been used by many popular applications on Google Play.
These are the advanced features delivered by the EventBus
library that you should be aware of:
Annotation-based subscription – You can define an subscription method by annotating an Android Activity
, Service
, or Fragment
instance method
Background and main thread event delivery – The subscriber could define in which thread the event will be delivered regardless of whether it was generated in a background or main thread
Event and subscriber inheritance – We can construct events or subscribers by extending (Java subclass) other events or subscribers:
No configuration...
First, we will define the POJO classes that would be submitted in the Bus
by the publisher to notify the interested entities whether the mobile network connectivity is available or not:
The MobileNetConnectedEvent
event is a POJO class that will be sent when the mobile network is available and will carry a string message with the detailed network state.
The MobileNetDisconnectedEvent
is an event that does not carry any information but it will notify the event subscriber that connection with the network was lost.
Now with events defined, we will create the BroadcastListener
that is going to receive Intents from the Android OS when any network connectivity changes (Wi-Fi, Mobile, …) occur on the device, and submits the events in the Bus when the mobile connectivity has changed:
With the Publisher
/Sender
class and event class already specified, all that remains is to register our Activity
class to receive both events and print the event sent on the screen.
Like we stated before, to receive any event from the Bus
, the Subscriber
entity, which could be any Java class on your code, will have to register on the Bus and subscribe to the event that it is interested in.
Any object will have to register on the Bus by calling the register function and provide a single on<EventName>(EventType)
method annotated with org.greenrobot.eventbus.Subscribe
for all the kind of event that it is interested in:
Let's implement the functions that are going to handle the MobileNetDisconnectedEvent
and the MobileNetConnectedEvent
event in our Activity:
EventBus
, by default, delivers the event in the subscriber in the same thread where the sender posted the event. Although this delivery scheme might work for most use cases, such as events that perform Android UI changes, when a long operation is executed in the event callback, the subscriber might block the main thread and prevent the system from running the UI rendering in time and drop some UI frames as a result.
To cope with time-consuming operations that might happen during the event delivery, the EventBus
library allows us to define the Thread in which the Bus
will call to deliver the event to the subscriber (ThreadMode
).
There are four modes supported by EventBus
that we can use to control the event delivering behavior:
Whenever we publish an event on the bus, the EventBus broker automatically delivers the event to all the current subscribers, and by default, will immediately clear the transient event. The new subscribers that register after the event is delivered to the current subscribers will not get the event.
There are situations when a new subscriber registers on the bus and no new event is produced or submitted on the Bus for a long period of time. As such, the subscriber will wait until the next event appears on the bus to produce any output from it.
Furthermore, when the new subscriber is responsible for updating an Android UI component like an Activity
or a Fragment
, the subscribers have to wait for a new event to occur, hence, it might delay the UI update for a significant amount of time.
To solve this problem, the EventBus
allows us to create Sticky
events that are kept in the memory and delivered to subscribers once they register on the Bus. EventBus
will keep the latest...
In some use cases, it could be convienient to invalidate a sticky event from the Bus and prevent a cached event from getting delivered to the following Subscribers. EventBus allows us to clear the sticky events by calling the following functions:
removeStickyEvent(<MyEventClass>)
– Removes and gets the recent sticky event for the given event type
removeStickyEvent(Object event)
- Removes the sticky event if it equals the passed event
removeAllStickyEvents()
- Removes the sticky events for all types
Let's use one removeStickyEvent
function to remove the latest sticky LocationEvent
from the bus:
After we remove the sticky event from the bus, the latest LocationEvent
will be removed from the bus and no event...
In this chapter, we learned about the publish/subscribe messaging pattern used to communicate between decoupled entities on an Android application. This pattern must be applied to send event notifications or data to one or more Android component recipients.
Next, we introduced to the reader the EventBus
, an optimized open source library that delivers the publish-subscribe pattern for the Android platform and provides advanced features such as sticky events and asynchronous event delivery.
Following that, we learned how set up the library, how to model events, and how to dispatch events on the default Bus
. The Bus, a shared entity that receives the events, will act as a broker and proxy for the events to the final recipients that previously subscribed to them.
We took a detailed look at Eventbus
threadMode
feature of EventBus that allows us to define the thread in which the Bus
delivers the event to the subscriber. Hence, we were able to consume events in different threads (background...