EventBus API: Your complete event manager for Android

Did you ever heard about Publish-Subscribe pattern in Software architecture?

Yes. It’s a messaging pattern where the senders of the message, called the publishers will never know who are going to receive those messages  and the receivers, also known as the subscribers, won’t know who sent those messages as well.

The publishers will just send the message, without knowing who is gonna receive it. They do their work right.

On the other hand, the receivers, I mean the subscribers, will subscribe what kind of message they want to get. Doesn’t matter who’ll send them. Well, why should they care? They’re gonna get what they need, right? 😀

Okay, let’s change the perspective a little. Think of an event as a message here. Now think about the publish-subscriber pattern. Yes, you got it right!

There will be event publishers instead of message publishers. And the subscribers will receive events instead of messages. So that whenever an event is published (of course by the publishers), the subscribers can receive that event and execute their code.

Here comes the awesomeness of the EventBus dependency for Android. It enables you to use publish-subscribe software architecture pattern. I’m using this library for several days and I’m just amazed. I don’t have to worry about event handlers now, I don’t need fragment interaction listeners, my code is clean and organised.

Okay let’s see how can we use this api in real life project. There’s a getting started page where you can find the instructions to use it. I recommend you to take a look on that page.

I’m creating a real world project so that we can get a hands on experience before we can use it.


First thing first, Let’s create an Android Studio project. I’m naming my project as EventBusDemo.

Add EventBus dependency on our app level build.gradle file:

compile 'org.greenrobot:eventbus:3.0.0'

We’ll have a textview and a button on our activity and a fragment (It’ll contain a textview and a button) so that we can illustrate the interaction between activity and fragment with eventbus as well.

Our goal is, whenever a button is clicked, all of the textviews (regardless activity textview or fragment textview) will be updated. So we have to post an even when a button is clicked, right? Then all of the methods that subscribes that event will update the textviews. or do whatever  they meant to do.


Let’s create our event first. It’s a plain old Java object(pojo). We name it MessageEvent

MessageEvent.java

package net.toracode.eventbusdemo.events;

public class MessageEvent {
    private String message;

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

    public String getMessage() {

        return message;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="net.toracode.eventbusdemo.MainActivity">

    <TextView
        android:textSize="15sp"
        android:id="@+id/activity_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView from activity" />

    <Button
        android:id="@+id/activity_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/activity_textview"
        android:text="Activity Button" />

    <RelativeLayout
        android:layout_marginTop="50dp"
        android:background="@color/colorAccent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/fragmentContainerLayout"
        android:layout_below="@id/activity_button" />
</RelativeLayout>

fragment_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="net.toracode.eventbusdemo.MainFragment">

    <TextView
        android:textColor="@android:color/white"
        android:textSize="15sp"
        android:id="@+id/fragment_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView from Fragment" />

    <Button
        android:id="@+id/fragment_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/fragment_textview"
        android:text="Fragment Button" />

</RelativeLayout>

MainActivity.java

package net.toracode.eventbusdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import net.toracode.eventbusdemo.events.MessageEvent;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {
    private TextView activityTextView;
    private Button activityButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // init components
        this.activityTextView = (TextView) this.findViewById(R.id.activity_textview);
        this.activityButton = (Button) this.findViewById(R.id.activity_button);

        // register eventbus
        EventBus.getDefault().register(this);

        this.getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainerLayout,new MainFragment()).commit();

        activityButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent("Activity Button Clicked!"));
            }
        });
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent messageEvent){
        this.activityTextView.setText(messageEvent.getMessage());
    }

}

We’ve registered eventbus on onCreate(). Best practice is to do it on onStart(). But it’s just a demo.

We have a method onMessageEvent() that subscribes MessageEvent, taking a MessageEvent object as a argument. That means whenever a message event will be posted this method will be executed. We’ve updated the textview with the message from message event.


We’ve implemented another subscriber method to update fragment textview in MainFragment.java.

So these two subscriber method will be executed without knowing who is the publishers or what’s inside this event. It’s just waiting for the MessageEvent to be published.

MainFragment.java

package net.toracode.eventbusdemo;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import net.toracode.eventbusdemo.events.MessageEvent;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;


public class MainFragment extends Fragment {
    private TextView fragmentTextView;
    private Button fragmentButton;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // init components
        this.fragmentTextView = (TextView) getView().findViewById(R.id.fragment_textview);
        this.fragmentButton = (Button) getView().findViewById(R.id.fragment_button);

        // Register eventBus
        EventBus.getDefault().register(this);

        this.fragmentButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent("Fragment Button Clicked!"));
            }
        });

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent messageEvent){
        this.fragmentTextView.setText(messageEvent.getMessage());
    }
}

We’ve posted event with custom message on onClickListeners of both activityButton and fragmentButton. When someone click those buttons, an event will be posted with a message. and those methods that subscribes that event will be executed, in this case, the textviews will be updated. And that’s how it works!

Leave a Reply

Your email address will not be published. Required fields are marked *