Skip to content

EventBus Example

Android EventBus Tutorial and Examples.

This is an android GreenRobot EventBus tutorial and examples.

What is EventBus?

EventBus is a library for Java and Android that simplifies communication between various components or parts of an application.

For example is in android we have several components like:

  • Activities.
  • Fragments.
  • Services.
  • and Threads.

Why EventBus?

Normally it's not very straight forward to communicate between or among these components. Normally you are forced to write lots of boilerplate code. For example:

  • To pass data between Activities you use Intents. To pass java objects you have to serialize and later deserialize them, thus leading to tight binding between the components.
  • To pass data between Fragments you use Bundles.
  • To pass data from Services you use Broadcast Managers.

These are all great, however we face the following issues:

  • Coupled hard to maintain code.
  • Lots of boilerplate code.
  • Objects can easily be passed without serialization and deserialization.

Publish/subscribe models 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

Hence great developers have come with solutions such as the publish/subscribe pattern of communication. In these:

  1. Publishers publish or post events.
  2. Subscribers listen or subscribe to those events.
  3. Event hold the information we want to pass.

This solves the coupling problem by modularising the components. The events allow for isolation of dependencies on each side. The event result is a bus allowing for communication pipeline that allows for readable and maintainable application.

Thread Delivery

EventBus can handle threading for you: events can be posted in threads different from the posting thread. A common use case is dealing with UI changes.

EventBus is a powerful library that respects your threading requirements when used to communicate. It does this by providing several thread delivery modes:

1. ThreadMode: POSTING

In this mode the subscribers are called in the same thread that posted that event. This is the default mode for eventbus.

// ThreadMode is optional as this is the default mode
@Subscribe(threadMode = ThreadMode.POSTING)
public void onEvent(MessageEvent event) {
    log(event.message);
}

2. ThreadMode: MAIN

In this mode the Subscribers will be called in the main thread.

@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
    textView.setText(event.message);
}

3. ThreadMode: MAIN_ORDERED

In this mode the Subscribers will be called in the main thread but the event is always enqueued for later delivery to subscribers, so the call to post will return immediately.

@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onEvent(MessageEvent event) {
    textView.setText(event.message);
}

4. ThreadMode: BACKGROUND

In this mode the Subscribers will be called in a background thread.

@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEvent(MessageEvent event){
    saveToDisk(event.message);
}

5. ThreadMode: ASYNC

In this mode the Event handler methods are called in a separate thread. This is always independent from the posting thread and the main thread.

@Subscribe(threadMode = ThreadMode.ASYNC)
public void onEvent(MessageEvent event){
    network.send(event.message);
}

Sticky Events

Stick events are events that EventBus will keep in memory and can be later delivered to subscribers or queried. Thus you don't have to write your own cache when working with data that are being emmitted continuosly like sensor data. EventBus can allow you work with latest emitted data through sticky events.

Here's how you post sticky event:

EventBus.getDefault().postSticky(new MessageEvent("Mr Stick event"));

Then to subscribe:

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
    textField.setText(event.message);
}

Alternatives to GreenRobot EventBus

Here are some alternatives to GreenRobot EventBus:

No. Alternative Description
1. Otto This is Deprecated.
2. RxJava

Installing EventBus

There are three ways of installing eventbus:

1. Via Gradle

If you are using gradle build system then here's the implementation statement. Check the latest version here.

implementation 'org.greenrobot:eventbus:3.1.1'

2. Via Maven

In your pom.xml add:

<dependency>
    <groupId>org.greenrobot</groupId>
    <artifactId>eventbus</artifactId>
    <version>3.1.1</version>
</dependency>

Here are EventBus examples:

Kotlin Android EventBus Example

Simple step by step eventbus examples for android.

Step 1: Install EventBus

Start by installing the eventbus as has been discussed above:

    implementation "org.greenrobot:eventbus:${versions.eventbus}"
    kapt "org.greenrobot:eventbus-annotation-processor:${versions.eventbusProcessor}"

Step 2: Design Layouts

(a). activity_empty.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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.example.eventbuskotlin.EmptyActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onPostStickyButtonClick"
        android:text="@string/action_post_sticky"/>

</RelativeLayout>

(b). fragment_blank.xml

<FrameLayout 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.example.eventbuskotlin.BlankFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

(c). activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    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="com.example.eventbuskotlin.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onPostButtonClick"
        android:text="@string/action_post" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onLaunchButtonClick"
        android:text="@string/action_launch_activity" />

    <FrameLayout
        android:id="@+id/containerFragment"
        android:layout_width="match_parent"
        android:layout_height="250dp" />

</LinearLayout>

Step 3: Initialize EventBus

Initialize it in the onCreate() method of the Application class:

package com.example.eventbuskotlin

import android.app.Application
import org.greenrobot.eventbus.EventBus

class EventBusApp: Application() {

    override fun onCreate() {
        super.onCreate()

        EventBus.builder()
                // have a look at the index class to see which methods are picked up
                // if not in the index @Subscribe methods will be looked up at runtime (expensive)
                .addIndex(MyEventBusIndex())
                .installDefaultEventBus()
    }

}

Step 4: Create Fragments

Create two fragments:

(a). BlankBaseFragment.kt

package com.example.eventbuskotlin

import android.support.v4.app.Fragment
import android.util.Log
import android.widget.Toast
import org.greenrobot.eventbus.EventBus

abstract class BlankBaseFragment : Fragment() {

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this)
    }

    open fun handleEvent(event: SampleEvent) {
        val className = this.javaClass.simpleName
        val message = "#handleEvent: called for " + event.javaClass.simpleName
        Toast.makeText(context, className + message, Toast.LENGTH_SHORT).show()
        Log.d(className, message)
    }

    class SampleEvent
}

(b). BlankFragment.kt

package com.example.eventbuskotlin

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import org.greenrobot.eventbus.Subscribe

class BlankFragment : BlankBaseFragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_blank, container, false)
    }

    @Subscribe // subscribe annotation in base class would not be picked up by index
    override fun handleEvent(event: BlankBaseFragment.SampleEvent) {
        super.handleEvent(event)
    }

    class SampleEvent
}

Step 5: Create Activities

We will have two activities:

(a). EmptyActivity.kt

package com.example.eventbuskotlin

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View

import org.greenrobot.eventbus.EventBus

class EmptyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_empty)
    }

    fun onPostStickyButtonClick(view: View) {
        EventBus.getDefault().postSticky(BlankBaseFragment.SampleEvent())
        finish()
    }

}

(b). MainActivity.kt

package com.example.eventbuskotlin

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.Toast
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this)
    }

    @Subscribe(sticky = true)
    fun handleEvent(event: BlankBaseFragment.SampleEvent) {
        val className = this.javaClass.simpleName
        val message = "#handleEvent: called for " + event.javaClass.simpleName
        Toast.makeText(this, className + message, Toast.LENGTH_SHORT).show()
        Log.d(className, message)

        // prevent event from re-delivering, like when leaving and coming back to app
        EventBus.getDefault().removeStickyEvent(event)
    }

    fun onPostButtonClick(view: View) {
        EventBus.getDefault().post(BlankBaseFragment.SampleEvent())
    }

    fun onLaunchButtonClick(view: View) {
        startActivity(Intent(this, EmptyActivity::class.java))
    }
}

Reference

Download all examples here Follow code author here