bh

Implementing an Event Bus With LiveData

Final product image
What You’ll Be Creating

At the last Google I/O, the Android team released a set of powerful Android Architecture Components. They call it:

A collection of libraries that help you design robust, testable, and maintainable apps. Start with classes for managing your UI component lifecycle and handling data persistence.

If you haven’t learnt about them, you are strongly advised to check out our awesome series here on Envato Tuts+ about Android Architecture Components by Tin Megali. Make sure you go dive in! 

  • Android SDK
    Introduction to Android Architecture Components
    Tin Megali

In this tutorial, I’ll show you how to use the LiveData components from the Android Architectural Components to create an event bus. An event bus can be used to effectively communicate between Android components or between layers of your application—for example, communicating to an Activity from an IntentService that a file has finished downloading. 

We’ll build a very simple app that triggers an IntentService to do some work—from an Activity. Our IntentService will then communicate back to the Activity when the work is completed. Our communication channel will be from the LiveData library. 

Prerequisites

To be able to follow this tutorial, you’ll need:

  • Android Studio 3.0 or higher
  • Kotlin plugin 1.1.51 or higher
  • a basic understanding of the Android Architectural Components (especially the LiveData component)
  • a basic understanding of an event bus

You can also learn all the ins and outs of the Kotlin language in my Kotlin From Scratch series.

  • Kotlin From Scratch: Variables, Basic Types, and Arrays

    Kotlin
  • Kotlin From Scratch: Classes and Objects

    Kotlin

1. Create an Android Studio Project

Fire up Android Studio 3 and create a new project with an empty activity called MainActivity

Android Studio new project screen

2. Add the Lifecycle Components

After creating a new project, specify the LifeCycle and the LiveData artifacts in your app module’s build.gradle. Note that as of this writing, the new architectural components are now in a stable version. So this means you can start using them in production apps. 

These artifacts are available at Google’s Maven repository. 

By adding the dependencies, we have taught gradle how to find the library. Make sure you remember to sync your project after adding them. 

3. Create the LifecycleOwner Activity Subclass

Here our MainActivity implements the LifecycleOwner interface. 

Our activity simply handles the standard activity lifecycle events. Inside each of the lifecycle events, it calls the registry.handleLifecycleEvent(), passing the corresponding event as a parameter.   

4. Create the Layout

We just have a Button that triggers the service. A TextView (invisible by default) shows the text "Work completed!" when the service communicates to our MainActivity

5. Initialize the Widgets

We declared our doWorkButton and resultTextView properties inside the MainActivity class with the lateinit modifier. We then initialize them inside the onCreate() method. Anytime the doWorkButton is clicked, we disable it (to prevent clicking the button more than once) and start our MyIntentService (we’ll get to that shortly). 

6. Create the Custom Event Class

We just create a simple event message class that we want to pass around on the event bus (or LiveData). 

You can add more properties to this class if you want. 

7. Service Implementation

We implemented an IntentService called MyIntentService. Remember that IntentService lives outside the activity scope and has a background thread, so it is recommended to perform time-consuming tasks such as downloading or fetching remote data via an API inside it.  

However, note that in Android 8.0 if you don’t make your IntentService a foreground service by using startForeground(), the Android system will not allow your service to run more than 1 minute—or else it will be stopped immediately. This mechanism is to efficiently manage system resources such as battery life. If your app is targeting Android 8.0, you are advised to use the JobIntentService instead. 

We create a nameless companion object whose companion class is MyIntentService. This companion object has a property called BUS, which is an instance of MutableLiveData.  Remember that companion objects are singletons, so this means that only a single instance of BUS exists. We also passed our CustomEvent as a type argument to the generic MutableLiveData class. 

Remember that the MutableLiveData class is a subclass of LiveData—and has a method called postValue() that can be called from a background thread. 

Inside onHandleIntent(), we have our business logic. Remember that this method is called on a background thread (one of the major differences between an IntentService and a normal Service). The IntentService ends immediately by itself when the onHandleIntent() method finishes its job.  

In our own case, we are simulating work being done (this work can be a file download or communicating with a remote API) by sleeping the current thread for 30 seconds. We then checked if our BUS has any active observers using the hasActiveObservers() method. If there are any, notify and pass our event message to them by using the method postValue(), or else we can simply show a notification (this was not coded in the example above for brevity’s sake). 

Remember to include the service in your manifest file.

8. Observer Implementation

We need at least one observer for our mechanism to be useful. So inside the MainActivity class, we are going to subscribe an anonymous observer. 

Inside the onCreate() of MainActivity, we got the event bus BUS from MyIntentService. Then we registered an observer for the event bus (i.e. LiveData) using the observe() method. Next, we registered and inlined an anonymous observer, using the MainActivity as LifecycleOwner. This anonymous observer gets notified when any of the following happens:

  • There is already data available in the LiveData when it subscribes. 
  • The data inside the LiveData gets modified. 

When either of these occurs, we get the event data (from the LiveData) on the main application thread as input to the lambda. We then do the following inside the lambda’s body:

  • Make the resultTextView visible.
  • Enable the doWorkButton.
  • Log our custom event property eventProp value to Logcat.

Remember the following about LiveData:

  • When a new observer is attached to our LiveData after a configuration change, LiveData will send the last data it received to the observer—even without us explicitly telling it to do so. In other words, it does this automatically. 
  • When the LifecycleOwner is destroyed, the observer will automatically be unsubscribed. 
  • Finally, LiveData is an observable that is lifecycle-aware. According to the docs:

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

9. Testing the App

Finally, you can run the app! Click the Do Work button and after 30 seconds, you’ll see the result. 

Tutorial project result

You can get the complete source code from our GitHub repo.

Conclusion

In this tutorial, you learned how to easily use the LiveData components from the Android Architectural Components to create an event bus—so as to effectively communicate with components of your app. 

I assume you’re aware of other libraries you can use for the same purpose, such as Android LocalBroadcastManager or the popular greenrobot EventBus to implement an event bus in your Android application. You can see that using the LiveData instead is preferable to them—because you avoid writing boilerplate or verbose code, and LiveData provides you with better flexibility. 

To learn more about coding for Android, check out some of our other courses and tutorials here on Envato Tuts+!

  • Android
    Communication Within an Android App With EventBus
    Chike Mgbemena
  • Android
    How to Get Started With Push Notifications On Android
    Ashraff Hathibelagal
  • Google Maps
    Getting Started With Google Maps for Android: Basics
    Paul Trebilcox-Ruiz
  • Android SDK
    Concurrency in RxJava 2
    Chike Mgbemena

Powered by WPeMatico

Leave a Comment

Scroll to Top