EventBus tutorial with examples Android 09.02.2017

EventBus tutorial with examples

You may be familiar with the various ways the Android framework relies on passing data between the various abstractions used:

  • Activities uses Intents to pass data between screens.
  • Fragments use multiple ways to communicate: Bundles to construct fragments, methods by the containing Activity to call, and the listener pattern for the Fragment to fire events.
  • Services rely on Broadcast Managers to send data to Applications.

One of primary issues of these approaches is that they can create strong dependencies between each component, making it difficult to change one part of the system without impacting another area.

Publish/subscribe pattern try to avoid this tight integration by relying on an event bus model. In this type of model, there are publishers and subscribers. Publishers are responsible for posting events in response to some type of state change, while subscribers respond to these events. The event acts as an intermediary for exchanging information, isolating and minimizing the dependencies between each side. In this way, message buses create a communication pipeline that is intended to help make your app more maintainable and scalable.

Publish/subscribe pattern

One additional benefit of using pub/sub frameworks is that they help facilitate passing Java objects between Activities, Fragments, or Services. You don't need to spend time serializing and deserializing data, which can often creates the tight bindings between these components. It also helps enforce more type-safety across complex Java objects.

There are som libraries which attempt to enable the event bus model, including EventBus, RxJava.

EventBus is a popular open-source library that simplifies communication between Activities, Fragments, Threads, Services, etc. using the publisher/subscriber pattern (observer design pattern). 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.

Like broadcasts, events are a tool for decoupling your application architecture, and they're especially useful when handling responses to asynchronous requests. Using the EventBus library, you can pass messages from one class to one or more classes in just a few lines of code.

The library is optimized for the Android platform and is very lightweight, only ~50k.

EventBus is a open-source library

Advantages of EventBus

  • Simplifies the communication between components.
  • Decouples event senders and receivers.
  • Performs well with Activities, Fragments, and background threads.
  • Avoids complex and error-prone dependencies and life cycle issues.

Useful scenarios to use EventBus in your project

  • Fragment and Activity Comminication.
  • Background Service to Fragment and/or Activity Comminication.

Methods of EventBus :

  • Method register registers your component to subscribe to events on the bus.
  • Method unregister stops receiving events of the bus.
  • Method post publishs your event on the bus.

To use EventBus, you should add the following to your build.gradle file (app-level file)

dependencies{
    ...
    compile 'org.greenrobot:eventbus:3.0.0'
}

You need the following four parts to send and receive messages through EventBus: bus, event, sender, ubscriber.

The bus. 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 EventBus instance:

EventBus eventBus = EventBus.getDefault();

The event. Events are just POJO (Plain Old Java Object) without any specific implementation:

public class MessageEvent {
    private final String message;

    public MessageEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

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!

The sender. 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().

EventBus.getDefault().post(new MessageEvent("New message!"));

The subscriber. Finally, someone should listen to MessageEvent. You can declare as many subscribers as you want and you are not limited to specific Android classes. You only have to call

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    EventBus.getDefault().register(this);
}

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().

The most important method is onEvent(), every class that intends to receive events from the event bus should contain this method. The name of this method is important, because the EventBus library uses the Java Reflection API to access this method.

You have to declare a method inside your subscriber class with the name onEvent() for every type of event you want to subscribe:

@Subscribe
public void onEvent(MessageEvent event){
    Toast.makeText(MainActivity.this, event.getMessage(), Toast.LENGTH_SHORT).show();
}

Of course, a subscriber can also listen to multiple events at the same time.

It is good idea to add following snippets to Activity code to suppress memory leak

@Override
protected void onPause() {
    super.onPause();
    EventBus.getDefault().unregister(this);
}

@Override
protected void onResume() {
    super.onResume();
    EventBus.getDefault().register(this);
}

That is how you can easily communicate between different parts of your application without having to write a lot of code or re-inventing the wheel with your own Subscriber or Publisher code!

Following is very simple example of MainActivity that send MessageEvent on Button click event. I've registered MainActivity as recipient and handle event in onEvent. I used layout and Activity from tutorial about Animation in Android.

public class MainActivity extends AppCompatActivity {
    TextView tvLabel;

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

        tvLabel = (TextView) findViewById(R.id.tvLabel);
    }

    public void anim(View v) {
        YoYo.with(Techniques.Shake)
                .duration(700)
                .playOn(tvLabel);

        EventBus.getDefault().post(new MessageEvent("New message!"));
    }

    @Subscribe
    public void onEvent(MessageEvent event){
        Toast.makeText(this, event.getMessage(), Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        EventBus.getDefault().unregister(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        EventBus.getDefault().register(this);
    }
}