Greenrobot’s EventBus is a tiny library that allows publish-subscribe style communication between components without requiring the components to explicitly register with one another.
That makes the data exchange between components like Activity, Fragment, Services and any kind of backgrounds threads pretty easy.
Why should I care about Event Bus?
The short answer: loose coupling.
The long answer: Normally, a software is divided into multiple layers like presentation layer (Activity, Fragment), business layer (e.g. UserService) and data layer (e.g. UserDao). Besides the technical layers, there are also functional layers.
Sometimes you want to process specific events that are interested for multiple parts of your application. Event Bus offers a solution for this case: It provides a centralized way to notify software components that are interested in a specific type of event. There exists no direct coupling between the code of the publisher of the event and the code that receives it. A well designed decoupled system will reduce the need to make changes across components in case anything changes.
An Event Bus can also massively reduce boilerplate code: No need for interfaces, callbacks for asynchronous communication or data propagation through all software layers. It keeps your software architecture decoupled and flexible.
The first step is to add the greenrobot EventBus dependency to your app’s build.gradle file. Don’t worry, the library is tiny (< 50 kB):
You need the following four parts to send and receive messages through your EventBus:
- The bus
- The event
- The sender
- The subscriber
For most applications, you will only need to use one EventBus object throughout your app. There is no need for explicit object instantiation. Just call anywhere in your code EventBus.getDefault() to receive the „default” event bus instance:
Events are just POJO (Plain Old Java Object) without any specific implementation:
An event is just an object that is posted from the sender on the bus and will be delivered to any receiver class subscribing to the same event type. That’s it!
You can post any event from any part of your whole Android application. Just get the default EventBus instance by calling EventBus.getDefault() and submit any event by calling post():
Ok, you have a bus, an event and already a sender. What’s missing? Right, someone should listen to our HelloWorldEvent. You can declare as many subscribers as you want and you are not limited to specific Android classes. Theoretically, every Java class can act as a subscriber.
You only have to call
to listen and subscribe to events.
If you want to use an Activity or Fragment as a subscriber, just call the statement above inside onStart(), onCreate() or onResume().
You should also unregister the subscriber. Just call unregister(this) if you do not longer need the Event Bus:
Listen to events:
You have to declare a method inside your subscriber class with the name onEvent for every type of event you want to subscribe:
No annotations and no configuration are necessary! You also don’t have to implement a specific interface. Just plain old and easily understandable code. That is a prime example for the software design paradigm convention over configuration.
- method name: onEvent
- parameter: only one method parameter
- visibility: public
- return type: void
Of course, a subscriber can also listen to multiple events at the same time. The following snippet shows the necessary code to prepare a Fragment to listen to two different types of event:
Is there anything else interesting?
The idea behind sticky events is pretty similar to the concept of sticky Intents: <br> Sometimes your app subscribes to an event but does not want to wait until the next event appears. Instead, it is also okay to retrieve and process the latest submitted event.
Consider the following case:
An app wants to show the current battery level in an Activity. The Activity does only receive the current battery info via an event when a change occurs (e.g. a drop from 43 % to 42 %). Let’s say the user opens the Activity the first time and regular (non-sticky) events are used. <br > What happens? The user must wait until a change of the battery level occurs to see the current battery level.
Sticky events solve this kind of problem. The Event Bus keeps the latest sticky event of a certain type in memory.
How does it work?
Sticky events are pretty similar to regular events. You only have to use postSticky() instead of post() and registerSticky() instead of register():
Let’s assume that this sticky event was posted few minutes ago.
What happens when the user wants to know the current battery level and enters the Activity right now?
During the registration of the sticky subscriber, the Activity will immediately get the latest posted BatteryLevelChangeEvent:
By the way: It is also possible to remove the latest sticky event by calling: removeStickyEvent(myStickyEvent). You can also remove all sticky events by calling removeAllStickyEvents().
You can easily adjust the EventBus by using the builder() method:
The following configuration methods exist:
Enables/Disables the logging of the information that a posted event has no subscribers.
Enables/Disables the submission of the NoSubscriberEvent in case a posted event has no subscriber.
By enabling this feature, the application fails hard when a subscriber method throws an Exception.
By default, EventBus catches every exception thrown from onEvent methods and sends a SubscriberExceptionEvent. You can disable this feature by calling this method with „false“.
By default, EventBus makes a method name verification for methods starting with onEvent to avoid typos. This method allows the exclusion of subscriber classes from this check.
For example, the following snippet creates an EventBus which does not send the event NoSubscriberEvent if there is no subscriber for a posted event:
I hope you have learned how to use the EventBus library. Although the library is very tiny, it is so helpful to reduce boilerplate code and for creating a decoupled system.
Make sure you have a clear concept of your App. Other developers could otherwise be pretty confused about the magic.
Also, avoid nested events (Sender A sends Event X to Subscriber B. Subscriber/Sender B sends Event Y to Subscriber C). Nested events increase the complexity dramatically and make debugging very hard.
Every design pattern has its pitfalls. You only have to respect them.
Thanks for reading. I will publish a new article about useful Android libraries every week. I’ll tweet out every new article at @andreasschrade. Feel free to follow if you’d be interested in reading more.