Publishing and Receiving events with EventBus library in Android

    When developing app, the popular matter we meet is passing message from a class to another - it's often called posting events. For example: communicating between BroadcastReceiver and Activity. In order to avoid some risks like leak memory, data losing,... you must manage the background threads well.
    There are many external libraries that helpful to us with this problem, for example: EventBus. It's is a powerful library and easy to implement. And this is publisher/subscriber pattern description:

    In this post, you are going to learn how to use the EventBus library by building a simple Android application that displays the "connecting Internet" status of the device. Because changes in the connecting status are system events, the app is going to have an Activity that needs to receive information from a BroadcastReceiver - the perfect scenario for using an event bus.
Additional Information
This post is part of a series called Android TOP useful libraries

Creating new project

    To use this library in your Android Studio project, please add it's dependency to your app/build.gradle:
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'de.greenrobot:eventbus:2.4.0' //EventBus dependency
}

    Because of checking Internet connection, you must add ACCESS_NETWORK_STATE permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Create a BroadcastReceiver class

    Firstly, for convenience in management, we put the static methods which checking Internet connection status into a class:
NetworkState.java
package info.devexchanges.eventbus;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class NetworkState {

    public static int TYPE_WIFI = 1;
    public static int TYPE_MOBILE = 2;
    public static int TYPE_NOT_CONNECTED = 0;

    public static int getConnectivityStatus(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        if (activeNetwork != null) {
            if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
                return TYPE_WIFI;

            if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
                return TYPE_MOBILE;
        }
        return TYPE_NOT_CONNECTED;
    }

    public static String getConnectivityStatusString(Context context) {
        int conn = getConnectivityStatus(context);
        String status = null;
        if (conn == TYPE_WIFI) {
            status = "Wifi enabled";
        } else if (conn == TYPE_MOBILE) {
            status = "Mobile data enabled";
        } else if (conn == TYPE_NOT_CONNECTED) {
            status = "Not connected to Internet";
        }

        return status;
    }
}

    In the BroadcastReceiver class, we must declare an EventBus instance first:
private final EventBus eventBus = EventBus.getDefault();

    Posting message with EventBus is very simple, just call post() method, your data will be ready in background thread and you can get it anytime later. This is full code for the BroadcastReceiver file:
NetworkReceiver.java
package info.devexchanges.eventbus;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import de.greenrobot.event.EventBus;

public class NetworkReceiver extends BroadcastReceiver {

    private final EventBus eventBus = EventBus.getDefault();

    @Override
    public void onReceive(Context context, Intent intent) {
        String status = NetworkState.getConnectivityStatusString(context);

        // Get current time
        Calendar c = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy");
        String formattedDate = df.format(c.getTime());

        String eventData = "@" + formattedDate + ": device network state: " + status;

        // Post the event with this line
        eventBus.post(eventData);
    }
}

Creating an Activity to display data

    Like in the BroadcastReceiver class, in this Activity, you must initialize the EventBus singleton like above (use getDefault() method).
    To allow a class to subscribe to events on the bus, the register() method is invoked. In our Activity, we call it in the onCreate() method.
    Similarly, to stop receiving events, the unregister() method is called. We call this method in the onDestroy() method to make sure all resources are freed.
    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. In this example, I only update network status to a TextView.
    Full code of this Activity:
MainActivity.java

package info.devexchanges.eventbus;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

import de.greenrobot.event.EventBus;

public class MainActivity extends AppCompatActivity {

    private EventBus eventBus = EventBus.getDefault();
    private LinearLayout linearLayout;

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

        linearLayout = (LinearLayout)findViewById(R.id.layout);

        eventBus.register(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        eventBus.unregister(this);
    }

    public void onEvent(String event) {
        LayoutParams lparams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        TextView tv = new TextView(this);
        tv.setLayoutParams(lparams);
        tv.setText(event);

        linearLayout.addView(tv);
    }
}

Never forget to registering your BroadcastReceiver in AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.devexchanges.eventbus">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <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>

        <receiver android:name=".NetworkReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>
    Running this application, you will see this output:

Conclusions & References

    Through this post, I hope that you can be learned the way to use the EventBus library. More details about it, visit the project on @Github. Moreover, you can contact to Green Robot team through their Homepage. Thanks for reading!

Share


Previous post
« Prev Post
Next post
Next Post »