Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

Using the Otto event bus in Android applications. This tutorial explains the usage of the Otto event bus library.

1. Otto as event bus system

1.1. Otto as event bus system

Otto is an open source project providing an event bus implementation. Components can publish and subscribe to events.

Otto has been a fork of the Guava event bus library from Google and been redesigned to support Android as well as possible. Unlike the Guava event bus, Otto does not consider event subscriptions from base classes or interface. This is done to improve performance of the library and to keep the application code simple and unambiguous.

1.2. Installation

If you are using Maven or Gradle as build system you can simply add a dependency to it.

dependencies {
  compile 'com.squareup:otto:1.3.8'
}
<dependency>
  <groupId>com.squareup</groupId>
  <artifactId>otto</artifactId>
  <version>1.3.8</version>
</dependency>

You could also download the JAR manually from Download Otto and add it to the classpath of your application.

1.3. When to use Otto?

Otto can be used to communicate between your activity and fragments or to communicate between an activity and a service.

An alternative solution would be the usage of RxJava. See Implementing an Event Bus With RxJava blog post for an example.

1.4. How to setup Otto?

The following description assumes your are using Otto in an Android application, even though it is possible to use it in an standard Java application.

To use Otto, create a singleton instance of the Bus class and provide access to it for your Android components. This is typically done in the Application object of your Android application.

public static Bus bus = new Bus(ThreadEnforcer.MAIN);

In this example the ThreadEnforcer.MAIN parameter is used,. This enforces Otto to send events always from the main thread. If you want to be able to send events from any thread use the ThreadEnforcer.ANY parameter.

1.5. How to register and unregister for events?

Event registration is done via the @Subcribe annotation on a public single parameter method. The method parameter is the event key, i.e., if such an data type is send via the Otto event bus the method is called.

Event receivers must register via the register method of the Bus class.

// subscribe for string messages

@Subscribe
public void getMessage(String s) {
    Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}

//subscribe for TestData messages

@Subscribe
public void getMessage(TestData data) {
    Toast.makeText(getActivity(), data.message, Toast.LENGTH_LONG).show();
}

//requires a registration e.g. in the onCreate method
bus.register(this);

To unregister from events use the unregister() method.

1.6. How to send events

For sending events it is not necessary to register with the event bus. Simple call the post() method of the `Bus class.

// post a string object
bus.post("Hello");

// example data to post
public class TestData {
    public String message;
}

// post this data
bus.post(new TestData().message="Hello from the activity");

1.7. How can new components receive the last event?

Sometimes new components, like a dynamically created fragment, should receive event data during their creation. If this case component can register as producer for such event data with the @Produce annotation.

Event receivers must register via the register method of the Bus class.

@Produce
public String produceEvent() {
    return "Starting up";
}

2. Exercise: Using Otto the event bus system

This is an example for the usage of Otto in an Android application.

Create a new Android project called com.vogella.java.library.otto based on the Empty Activity with Fragment template.

Add the dependency to the build.gradle file.

dependencies {
    // more stuff
    compile 'com.squareup:otto:1.3.5'
    // more stuff

}

The activity_main.xml layout file of the activity should look like the following.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.vogella.android.otto.MainActivity"
    tools:ignore="MergeRootFrame" />

The fragment_main.xml layout file of the fragment should look like the following.

<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"
    tools:context="com.vogella.android.otto.MainActivity$PlaceholderFragment" >

    <Button
        android:id="@+id/fragmentbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Send event from fragment" />

</RelativeLayout>

Add an fragment and add it dynamically to your activity. Send an event from the fragment to the activity and vice versa. Display in both case a Toast.

package com.vogella.android.otto;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.squareup.otto.Bus;
import com.squareup.otto.Produce;
import com.squareup.otto.Subscribe;
import com.squareup.otto.ThreadEnforcer;

import library.java.vogella.com.otto.R;

public class MainActivity extends Activity {

    public static Bus bus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
        }
        bus = new Bus(ThreadEnforcer.MAIN);
        bus.register(this);
    }

    @Subscribe
    public void getMessage(String s) {
        Toast.makeText(this, s, Toast.LENGTH_LONG).show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            TestData t = new TestData();
            t.message="Hello from the activity";
            bus.post(t);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public class TestData {
        public String message;
    }


    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            View button = rootView.findViewById(R.id.fragmentbutton);
            button.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    bus.post("Hello from the Fragment");
                }
            });
            bus.register(this);
            return rootView;
        }

        @Subscribe
        public void getMessage(MainActivity.TestData data) {
            Toast.makeText(getActivity(), data.message, Toast.LENGTH_LONG).show();
        }
    }

    @Produce
    public String produceEvent() {
        return "Starting up";
    }

}
The example is intentional simple. In a real Android application you would created the Bus singleton in the Application class.

3. About this website

4. OkHttp resources

4.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.