EventBus Android Example [Full Tutorial]

Imagine a scenario in which you have an Activity containing with 2 fragments and you want your activity to be notified of any event in your fragments, also the vice versa. Simple solution is to attach listeners to both your fragments and activity. Now as the number of events increase the code becomes complex also both the fragments and your activity need to be tightly coupled with each other. All this becomes very difficult to manage. To solve problems like these we have Android EventBus library. EventBus is open source lightweight android library which uses publisher-subscriber pattern to communicate between Android components.  Following are some of the advantages of using EventBus library

  • Loose coupling between event senders and receivers
  • Very easy to implement as it uses annotation processing
  • Enables sending events across threads.
  • Tiny jar yet powerful and highly optimized

In this tutorial we will demonstrate a complete EventBus Android Example explaining all its features and uses in an Android App

eventbus
Flow Diagram for EventBus

Add the dependency

First step in this EventBus android example is to add the following dependency in build.gradle of our project

implementation 'org.greenrobot:eventbus:3.0.0'

Posting Events

In this section we will learn how to send any event with EventBus library. This event will be received by all the registered event handlers across the application. Before sending an Event let us first define our custom event class. This is a simple POJO class which can be customized as per our use case. Since this is just an example we have a simple Java class MyCustomEvent. Look at the code snippet below for reference

public class MyCustomEvent{
    String data;

    public MyCustomEvent(String data){
        this.data=data;
    }
}

Now you can post this event by this simple one line code

EventBus.getDefault().post(new MyCustomEvent("Custom event data"));
  • EventBus.getDefault() returns an EventBus object . Calling the post method on this EventBus object will fire the Event. Simple, isn’t it?

Subscribing to Events

So far we saw how to send events using EventBus library. In this section we will learn how to listen to those events

In order to listen for events we need to register our subscriber with EventBus. Here subscriber refers to the android class/component where you intend to handle the event. Like in activity/fragment we should ideally register in onStart() method. Similarly our subscriber should be unregistered in onStop(). Look at the code snippet below for reference

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
    }

    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    public void onStop(){
        super.onStop();
        EventBus.getDefault().unregister(this);

    }
}
  • In the above snippet we register the subscriber(MainActivity.java) by calling EventBust.getDefault().register(this) in onStart() method. Similarly we unregister it using EventBust.getDefault().unregister(this) in onStop() method. This ensures that our activity will listen for events as long as its active.
  • With our activity now listening for events we now need to create a event handler to respond to these events. This can be done by adding a @Subscribe annotation to a method and specify the event (which you intend to handle) as method parameter. This method will then act as the event handler and will be invoked everytime the event is fired. Look at the code snippet below for reference.
/*
   Method will act as the event handler for MyCustomEvent
   */
   @Subscribe
   public void customEventReceived(MyCustomEvent event){
       textView.setText(event.data);
   }
  • In the above snippet customEventReceived(MyCustomEvent) method will be invoked everytime  MyCustomEvent is fired as long as the activity is active. Similarly you can add multiple event handlers for different events in a single class.
  • This finishes the basic implementation of EventBus. As you must have seen its very loosely coupled as you neither need to attach any listener nor need to manually send event to multiple receivers. This simplifies communication between multiple Android components.

As of EventBus 3 you can choose any name for your event handler method. Till EventBus 2.0 you had to follow a naming convention

Working with Threads

One of the biggest advantages with EventBus is its ability to post events across threads with minimal effort. This means you can post events to any thread (background or UI). This becomes very useful as in Android all UI changes need to be done on main thread whereas network operations or any long running task should be done on a separate background thread. With EventBus you just need to add a annotation specifying thread mode on your event handler method and this will ensure that this method is invoked on the specified thread. Following are the different thread modes

  • ThreadMode.Posting
    This is the default ThreadMode for a event handler if no ThreadMode is specified. This mode implies that the event handler method will be called on the same thread as the one posting the event. As there is no thread switching involved this is very efficient. All the event handlers are called synchronously once the event is posted. We should avoid any long running tasks in the event handler as that might block the posting thread, which can also be the main thread. Look at the snippet below for reference.

    @Subscribe(threadMode = ThreadMode.POSTING)
    public void customEventReceived(MyCustomEvent event){
       Toast.makeText(this,"Custom Event Received",Toast.LENGTH_SHORT).show();
    }
  • ThreadMode.MAIN
    This mode implies that the event handler will be called on the main thread. Therefore we should avoid running any long tasks in the event handler which could block the main thread. If the thread posting this event is also the main thread then all the event handlers are called synchronously.

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void customEventReceived(MyCustomEvent event){
       Toast.makeText(this,"Custom Event Received",Toast.LENGTH_SHORT).show();
    }
  • ThreadMode.Background
    This mode implies that the event handler will be called on the background thread. If the event is also posted from a background thread then the event handler is called on the same thread. Whereas if the event is posted from main thread then the event handler is invoked on a separate background thread. For this mode a single background thread is used to post all the events sequentially. As with other modes, we should running long tasks in this mode as that will block the single background thread.

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void customEventReceived(MyCustomEvent event){
       Toast.makeText(this,"Custom Event Received",Toast.LENGTH_SHORT).show();
    }
  • ThreadMode.Async
    This mode implies that the event handler method will always be called on a separate thread. This thread is different from posting thread or the main thread. In this mode the EventBus doesn’t wait for the event handler to complete its execution, thus this is useful when we want to run a long task in our event handler. For every event handler EventBus creates a new background thread which also means developers should avoid running a lot of event handler methods with this mode at the same time as that might lead to multiple concurrent threads.

    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void customEventReceived(MyCustomEvent event){
       Toast.makeText(this,"Custom Event Received",Toast.LENGTH_SHORT).show();
    }

Event Handler Priority

With EventBus you can even assign a priority to a event handler method which will determine the sequence in which the event handlers will be executed. The default priority is 0. This priority is only valid among event handler methods of the same mode which means that it wont effect the order of delivery for event handlers with different ThreadModes.

@Subscribe(priority = 1)
public void customEventReceived(MyCustomEvent event){
    
}

Canceling Event delivery

One very interesting feature of EventBus library is the ability to cancel further event delivery from a Event Handler method. This could come very handy for a lot of use cases where you would like to stop event delivery midway. Calling  EventBus.getDefault().cancelEventDelivery(event)  from a event handler method would cancel all the further delivery of events. Look at the code snippet below for reference.

@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void customEventReceived(MyCustomEvent event){
    EventBus.getDefault().cancelEventDelivery(event);
}

Conclusion

This brings us to the end of EventBus Android example. If you liked this tutorial do checkout some of our other tutorials at Android Examples and if you have any questions feel free to comment below.