Otto Event Bus Library Tutorial With Example

Imagine an app that has several activities and fragments in it. Also, we need to communicate among these components. By using interfaces, we can achieve it. But, it will be a headache to maintain and debug these codes. Moreover, components will be dependent on each other i.e. They will be tightly coupled. Also, It will be difficult to debug these codes. So, we need something that can be used to communicate between these components while keeping them independent from each other.

There are some popular android libraries that can be used for this purpose.
a. Guava event bus library.
b. Otto event bus library.

We have already talked about How to setup Guava event bus library and create Sticky Event using Guava EventBus Library. You can go to these posts to learn more about Guava event bus library.

Other library (Otto event bus) is specifically designed for Android applications. Otto is an event bus designed to work as publisher-subscriber model. It is forked from Guava and adds unique functionality for android platform. You can communicate easily between different parts of application while keeping them independent from each other.

Output

Tutorialwing - Otto Event Bus tutorial output

Tutorialwing – Otto Event Bus tutorial output

Video Output

Source Code

Android Otto EventBus Tutorial Source Code

1. Getting started

In this tutorial, we will learn about otto event bus library.

1.1 Creating new project

Follow steps written below to create a new project.
a. Goto File –> New –> New Project. Then, Write application name as OttoLibraryTutorial and click next.
b. Select Minimum SDK 15 or more –> click next –> Select Empty Activity –> click next –> click finish.
If you have followed above process correctly, you will get a newly created project successfully.

1.2 Installation

a. You can download the JAR file from this url . Add it to libs folder.
b. Using Gradle
Goto app/build.gradle and add following gradle into it.

compile 'com.squareup:otto:1.3.8'

c. Using MAVEN .

<dependency>
  <groupId>com.squareup</groupId>
  <artifactId>otto</artifactId>
  <version>1.3.8</version>
</dependency>

Once you’ve installed Otto, add the following lines to your proguard-project.txt file. This ensures your annotated methods aren’t removed by ProGuard.

-keepattributes *Annotation*
-keepclassmembers class ** {
    @com.squareup.otto.Subscribe public *;
    @com.squareup.otto.Produce public *;
}

In this tutorial, we are going to use gradle. So, add gradle into app/build.gradle file.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'

    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.squareup:otto:1.3.8'
}

1.3 Set up Otto event bus

You can create an instance of Bus as below.

Bus bus = new Bus();

1.3.1 Creating Otto event bus singleton class

Create a singleton class that returns an instance of Otto event bus. Also, return the same instance throughout the application. Create a class GlobalBus into tutorialwing.com.ottolibrarytutorial. Then, add the method that returns instance of otto event bus. Finally, the singleton class would look like below.
GlobalBus.java

package tutorialwing.com.ottolibrarytutorial;
import com.squareup.otto.Bus;
public class GlobalBus {
	private static Bus sBus;
	public static Bus getBus() {
		if (sBus == null)
			sBus = new Bus();
		return sBus;
	}
}

1.3.2 Creating events

In this tutorial we are going to show how to communicate between fragment and activity. So, we will create events for it. Create a class named Events.java into tutorialwing.com.ottolibrarytutorial package. Then, create two events FragmentActivityMessage and ActivityFragmentMessage in it. FragmentActivityMessage will be used when we send information from fragment to activity. ActivityFragmentMessage will be used when we send information from activity to fragment. Finally, Events.java class would be as below.

package tutorialwing.com.ottolibrarytutorial;

public class Events {

	public static class FragmentActivityMessage {

		private String message;

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

		public String getMessage() {
			return message;
		}
	}

	public static class ActivityFragmentMessage {

		private String message;

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

		public String getMessage() {
			return message;
		}
	}
}

1.4 How to register and unregister Otto event bus

@Subscribe annotation is used to subscribe any event. This is used with a public method that accepts a single parameter( event we want to listen) .

//Subscribe for event we want to receive.
@Subscribe

public void getMessage(EventName event) {
     // Write code to perform operation after receiving this event.

}

You need to register with the bus. So, write busInstance.register(this) in onStart method. After use, you should unregister it. So, write busInstance.unregister(this) in onStop method. However, you should register the bus just before needed and unregister it when you are done with it.

A complete example, suppose we are using it in Activity

@Override

protected void onStart() {

	super.onStart();

	GlobalBus.getBus().register(this);

}

//Subscribe to listen the event


@Subscribe

public void getMessage(EventName event) {

	//Write code to perform some action.
}

@Override

protected void onStop() {

	super.onStop();

	GlobalBus.getBus().unregister(this);

}

1.5 How to send event using Otto event bus

When-ever you want to post or send any event, you need to write busInstance.post(new EventName(“some data”)). You do not need to register/unregister to/from the bus to post any event.
Example:

// An event to post.
public class FragmentActivityMessage {

	public String message;

}
// Post event with some message.
busInstance.post(new FragmentActivityMessage(“Hello Tutorialwing”));

1.6 How to receive the last event

Suppose we want to receive the current known value for specific event upon their registration. Otto uses the concepts of producer to achieve this goal. Producer provides immediate callback to any subscribers upon their registration.

To Create a producer, annotate a method with @Produce. This method does not take any parameter and it’s return type will be the event whose initial value we want to get. If we are keeping track of the last value of the event, we can use it as below.

@Produce

public EventName getMessage(EventName event) {

	// Suppose we have last value..
	return new EventName(lastValue);
}

Like Subscriber, Producer must also be registered to the bus using busInstance.register(this).

1.7 Use Otto event bus in Different thread mode

If you want to use otto event bus in different threads, you can pass thread name on which you want to use it. Otto uses ThreadEnforcement mechanism for it.

// Both of these are functionally equivalent.
Bus bus1 = new Bus();	//Default to ThreadEnforcer.ANY
Bus bus2 = new Bus(ThreadEnforcer.MAIN);

We have completed all the setups we need to complete this tutorial.




2.0 How to use Otto event bus?

In this section, We will see an example to use otto event bus to communicate between fragment and activity. Similarly, you can use this library to communicate between any components of android applications.

2.1 Update Values Folder

We shouldn’t do hardcoding. so, I have added some constants in values folders. You just copy/paste these codes into respective value folders. You would need these constants after few moments.
values/dimens.xml

<resources>

    <dimen name="margin_large">10dp</dimen>

    <dimen name="margin_medium">5dp</dimen>

    <dimen name="padding_large">10dp</dimen>

    <dimen name="padding_medium">5dp</dimen>

</resources>

values/strings.xml

<resources>

    <string name="app_name">OttoLibraryTutorial</string>

    <string name="message_received">Message Received:</string>

    <string name="message_main_activity">Message received in MainActivity : </string>

    <string name="message_second_activity">Message received in SecondActivity : </string>

    <string name="message_fragment">Message received in Fragment : </string>

    <string name="title_main">MainActivity</string>

    <string name="title_fragment">Fragment</string>

    <string name="title_stickyEvent">StickyEvent Example</string>

    <string name="hint_message">Enter message</string>

    <string name="send_message_fragment">Send message to Fragment</string>

    <string name="send_message_activity">Send message to Activity</string>

    <string name="show_second_activity">Show Second Activity</string>

</resources>

values/colors.xml and values/styles.xml are not changed. So, it is left untouched.

2.2 Final AndroidManifest.xml folder code

AndroidManifest.xml file would look like as below

<?xml version="1.0" encoding="utf-8"?>
<manifest package="tutorialwing.com.ottolibrarytutorial"
          xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

2.3 Write code to send and receive event in Activity

In MainActivity, We are sending ActivityFragmentMessage event and receiving FragmentActivityMessage event. Notice that we have registered to bus in onStart method and unregistered it in onStop method. Also, @Subscribe annotation has been used to receive FragmentActivityMessage event. After receiving the event, message is shown in the textView and as a Toast message. In sendMessageToFragment method, We are taking the input entered by user in the textfield and creating an event using this message, then, posting this event to be listened by Fragment.

MainActivity.java

package tutorialwing.com.ottolibrarytutorial;

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

import com.squareup.otto.Subscribe;

public class MainActivity extends AppCompatActivity {

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

		addFragment();
	}

	@Override
	protected void onStart() {
		super.onStart();
		GlobalBus.getBus().register(this);
	}

	private void addFragment() {
		getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, new UserFragment()).commit();
	}

	public void sendMessageToFragment(View view) {
		EditText etMessage = (EditText) findViewById(R.id.activityData);
		Events.ActivityFragmentMessage activityFragmentMessageEvent =
				new Events.ActivityFragmentMessage(String.valueOf(etMessage.getText()));
		GlobalBus.getBus().post(activityFragmentMessageEvent);
	}

	@Subscribe
	public void getMessage(Events.FragmentActivityMessage fragmentActivityMessage) {
		TextView messageView = (TextView) findViewById(R.id.message);
		messageView.setText(getString(R.string.message_received) + " " + fragmentActivityMessage.getMessage());

		Toast.makeText(getApplicationContext(),
				getString(R.string.message_main_activity) + " " + fragmentActivityMessage.getMessage(),
				Toast.LENGTH_SHORT).show();
	}

	@Override
	protected void onStop() {
		super.onStop();
		GlobalBus.getBus().unregister(this);
	}
}

xml file contains the UI that is being used to show communication between activity and fragment. activity_main.xml file contains following code.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/padding_large"
    android:background="#cfcfcf">

    <RelativeLayout
        android:id="@+id/activityLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:padding="@dimen/padding_medium">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/margin_medium"
            android:text="@string/title_main"
            android:textStyle="bold"/>

        <TextView
            android:id="@+id/message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/title"/>

        <EditText
            android:id="@+id/activityData"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/message"
            android:hint="@string/hint_message"/>

        <Button
            android:id="@+id/sendMessageToFragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/activityData"
            android:layout_centerHorizontal="true"
            android:onClick="sendMessageToFragment"
            android:text="@string/send_message_fragment"/>

    </RelativeLayout>

    <LinearLayout
        android:id="@+id/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/activityLayout"
        android:layout_marginTop="@dimen/margin_large"
        android:orientation="vertical">
    </LinearLayout>

</RelativeLayout>



2.4 Write code to send and receive event in Fragment

We will write code in fragment to receive and send event. So, create a Fragment (named as “UserFragment”) in tutorialwing.com.ottolibrarytutorial package. Also, create an xml file fragment_user.xml for it in res/layout folder. In UserFragment, we are sending FragmentActivityMessage event and receiving ActivityFragmentMessage event. Notice that we have registered to bus in onStart method and unregistered it in onStop method. Also, @Subscribe annotation has been used to receive ActivityFragmentMessage event. After receiving the event, message is shown in the textView and as a Toast message. In sendMessageToActivity method, We are taking the input entered by user in the textfield and creating an event using this message, then, posting this event to be listened by Activity.

UserFragment.java

package tutorialwing.com.ottolibrarytutorial;

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.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.otto.Subscribe;

public class UserFragment extends Fragment {

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return inflater.inflate(R.layout.fragment_user, container, false);
	}

	@Override
	public void onStart() {
		super.onStart();
		GlobalBus.getBus().register(this);
	}

	@Override
	public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		setClickListener(view);
	}

	public void setClickListener(final View view) {
		Button btnSubmit = (Button) view.findViewById(R.id.submit);
		btnSubmit.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				sendMessageToActivity();
			}
		});
	}

	private void sendMessageToActivity() {
		EditText etMessage = (EditText) getView().findViewById(R.id.editText);
		Events.FragmentActivityMessage fragmentActivityMessageEvent =
				new Events.FragmentActivityMessage(String.valueOf(etMessage.getText()));

		GlobalBus.getBus().post(fragmentActivityMessageEvent);
	}

	@Subscribe
	public void getMessage(Events.ActivityFragmentMessage activityFragmentMessage) {
		TextView messageView = (TextView) getView().findViewById(R.id.message);
		messageView.setText(getString(R.string.message_received) + " " + activityFragmentMessage.getMessage());

		Toast.makeText(getActivity(),
				getString(R.string.message_fragment) + " " + activityFragmentMessage.getMessage(),
				Toast.LENGTH_SHORT).show();
	}

	@Override
	public void onStop() {
		super.onStop();
		GlobalBus.getBus().unregister(this);
	}
}

fragment_user.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:padding="@dimen/padding_medium">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/margin_medium"
        android:text="@string/title_fragment"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"/>

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/message"
        android:hint="@string/hint_message"/>

    <Button
        android:id="@+id/submit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText"
        android:layout_centerHorizontal="true"
        android:text="@string/send_message_activity"/>

</RelativeLayout>

Output

If you run the app, you will see section for UserFragment and MainActivity separately. Then, Enter the message you to send to fragment in MainActivity and vice versa. You will see output as shown above.

Conclusion

Android Otto event bus is one of the popular android libraries which is based on publisher/subscriber pattern to communicate between different components in the application.

2 Comments

  1. motoapk Quá hay April 30, 2017

Leave a Reply