---
title: "Using Android Architecture Components with Firebase Realtime Database (Part 3)"
description: "Using Android Architecture Components with Firebase Realtime Database (Part 3)"
published: "2017-12-22"
last_updated: "2017-12-22"
authors:
  - "Doug Stevenson (Developer Advocate)"
categories:
  - "Android"
  - "Realtime Database"
  - "Best Practices"
canonical_url: "https://firebase.blog/posts/2017/12/using-android-architecture-components_22"
---

# Using Android Architecture Components with Firebase Realtime Database (Part 3)

*Published December 22, 2017 by Doug Stevenson (Developer Advocate)*

---
Hey, welcome to part 3 in this series about using lifecycle-aware Android Architecture Components with Firebase Realtime Database. In [part 1](https://firebase.googleblog.com/2017/12/using-android-architecture-components.html), we started with a simple Activity that uses database listeners to keep its UI fresh as data changes in the database. We converted that to use LiveData and ViewModel to remove the boilerplate of dealing with the listeners during the Activity lifecycle. Then, in [part 2](https://firebase.googleblog.com/2017/12/using-android-architecture-components_20.html), we completely refactored away all mention of Realtime Database from the Activity, and implemented a performance enhancement. This optimization uses `MediatorLiveData` and some threading, for the case where data manipulation might be too expensive operation to perform on the main thread.

There's one more optimization that can be applied in the code. It could have a large impact on performance, depending on how much data your database listeners are receiving. It has to do with how our `FirebaseQueryLiveData` implementation deals with the database listener during its `onActive()` and `onInactive()` methods. Here it is again:

```java
public class FirebaseQueryLiveData extends LiveData<DataSnapshot> {
    private static final String LOG_TAG = "FirebaseQueryLiveData";

    private final Query query;
    private final MyValueEventListener listener = new MyValueEventListener();

    public FirebaseQueryLiveData(Query query) {
        this.query = query;
    }

    public FirebaseQueryLiveData(DatabaseReference ref) {
        this.query = ref;
    }

    @Override
    protected void onActive() {
        query.addValueEventListener(listener);
    }

    @Override
    protected void onInactive() {
        query.removeEventListener(listener);
    }

    private class MyValueEventListener implements ValueEventListener {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            setValue(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e(LOG_TAG, "Can't listen to query " + query, databaseError.toException());
        }
    }
}
```

The key detail to note here is that a database listener is added during `onActive()` and removed during `onInactive()`. The Activity that makes use of `FirebaseQueryLiveData` executes this code during its `onCreate()`:

```java
HotStockViewModel viewModel = ViewModelProviders.of(this).get(HotStockViewModel.class);
LiveData<DataSnapshot> liveData = viewModel.getDataSnapshotLiveData();

liveData.observe(this, new Observer<DataSnapshot>() {
    @Override
    public void onChanged(@Nullable DataSnapshot dataSnapshot) {
        if (dataSnapshot != null) {
            // update the UI here with values in the snapshot
        }
    }
});
```

The observer here follows the lifecycle of the `Activity`. `LiveData` considers an observer to be in an active state if its lifecycle is in the [STARTED](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#STARTED) or [RESUMED](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#RESUMED) state. The observer transitions to an inactive state if its lifecycle is in the [DESTROYED](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State.html#DESTROYED) state. The [onActive()](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html#onActive()) method is called when the `LiveData` object has at least one active observer, and the [onInactive()](https://developer.android.com/reference/android/arch/lifecycle/LiveData.html#onInactive()) method is called when the `LiveData` object doesn't have any active observers. So, what happens here when the Activity is launched, then goes through a [configuration change](https://developer.android.com/guide/topics/resources/runtime-changes.html) (such as a device reorientation)? The sequence of events (when there is a single UI controller observing a `FirebaseQueryLiveData`) is like this:

1.  Activity is started.
2.  LiveData is observed and becomes active, invoking its `onActive()` method.
3.  **Database listener is added.**
4.  Data is received; UI is updated.
5.  _Device is reoriented, Activity is destroyed_
6.  LiveData is unobserved and becomes inactive, invoking its `onInactive()` method.
7.  **Database listener is removed.**
8.  New Activity is started to take the place of the original.
9.  LiveData is observed and becomes active again, invoking its `onActive()` method.
10.  **Database listener is added.**
11.  Data is received; UI is updated.

I've bolded the steps that deal with the database listener. You can see here the Activity configuration change caused the listener to be removed and added again. These steps spell out the cost of a second round trip to and from the Realtime Database server to pull down all the data for the second query, even if the results didn't change. I definitely don't want that to happen, because `LiveData` already retains the latest snapshot of data! This extra query is wasteful, both of the end user's data plan, and and counts against the quota or the bill of your Firebase project.

### How do we prevent this unnecessary query?
There's no easy way to change the way that the `LiveData` object becomes active or inactive. But we can make some guesses about how quickly that state could change when the Activity is going through a configuration change. Let's make the assumption that a configuration change will take no more than two seconds (it's normally much faster). With that, one strategy could add a delay before `FirebaseQueryLiveData` removes the database listener after the call to `onInactive()`. Here's an implementation of that, with a few changes and additions to `FirebaseQueryLiveData`:

```java
private boolean listenerRemovePending = false;
private final Handler handler = new Handler();
private final Runnable removeListener = new Runnable() {
    @Override
    public void run() {
        query.removeEventListener(listener);
        listenerRemovePending = false;
    }
};

@Override
protected void onActive() {
    if (listenerRemovePending) {
        handler.removeCallbacks(removeListener);
    }
    else {
        query.addValueEventListener(listener);
    }
    listenerRemovePending = false;
}

@Override
protected void onInactive() {
    // Listener removal is schedule on a two second delay
    handler.postDelayed(removeListener, 2000);
    listenerRemovePending = true;
}
```

Here, I'm using a [`Handler`](https://developer.android.com/reference/android/os/Handler.html) to schedule the removal of the database listener (by posting a `Runnable` callback that performs the removal) on a two second delay after the `LiveData` becomes inactive. If it becomes active again before those two seconds have elapsed, we simply eliminate that scheduled work from the `Handler`, and allow the listener to keep listening. This is great for both our users and our wallets!

Are you using lifecycle-aware Android Architecture components along with Firebase in your app? How's it going? Join the discussion of all things Firebase on our Google group [firebase-talk](https://groups.google.com/forum/#!forum/firebase-talk).
