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

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

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

---
Welcome to part 2 of this blog series on using lifecycle-aware Android Architecture Components (`[LiveData](https://developer.android.com/topic/libraries/architecture/livedata.html)` and `[ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel.html)`) along with [Firebase Realtime Database](https://firebase.google.com/products/database/) to implement more robust and testable apps! [In the first part](https://firebase.googleblog.com/2017/12/using-android-architecture-components.html), we saw how you can use `LiveData` and `ViewModel` to simplify your Activity code, by refactoring away most of the implementation details of Realtime Database from an Activity. However, one detail remained: the Activity was still reaching into the `DataSnapshot` containing the stock price. I'd like to remove all traces of the Realtime Database SDK from my Activity so that it's easier to read and test. And, ultimately, if I change the app to use [Firestore](https://firebase.google.com/products/firestore/) instead of Realtime Database, I won't even have to change the Activity code at all.

Here's a view of the data in the database:

![image1](https://firebasestorage.googleapis.com/v0/b/first-class-blog.appspot.com/o/blog-assets%2F2017%2F12%2Fusing-android-architecture-components_20%2Foptimized%2Fimage1.jpg?alt=media)

and here's the code that reads it out of `DataSnapshot` and copies into a couple TextViews:

```java
// update the UI with values from the snapshot
String ticker = dataSnapshot.child("ticker").getValue(String.class);
tvTicker.setText(ticker);
Float price = dataSnapshot.child("price").getValue(Float.class);
tvPrice.setText(String.format(Locale.getDefault(), "%.2f", price));
```

The Realtime Database SDK makes it really easy to convert a DataSnapshot into a [JavaBean](https://en.wikipedia.org/wiki/JavaBeans) style object. The first thing to do is define a bean class whose getters and setters match the names of the fields in the snapshot:

```java
public class HotStock {
    private String ticker;
    private float price;

    public String getTicker() {
        return ticker;
    }

    public void setTicker(String ticker) {
        this.ticker = ticker;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public String toString() {
        return "{HotStock ticker=" + ticker + " price=" + price + "}";
    }
}
```

Then I can tell the SDK to automatically perform the mapping like this:

```java
HotStock stock = dataSnapshot.getValue(HotStock.class)
```

After that line executes, the new instance of `HotStock` will contain the values for `ticker` and `price`. Using this handy line of code, I can update my `HotStockViewModel` implementation to perform this conversion by using a [transformation](https://developer.android.com/topic/libraries/architecture/livedata.html#transform_livedata). This allows me to create a `LiveData` object that automatically converts the incoming `DataSnapshot` into a `HotStock`. The conversion happens in a `Function` object, and I can assemble it like this in my `ViewModel`:

```java
// This is a LiveData<DataSnapshot> from part 1
private final FirebaseQueryLiveData liveData = new FirebaseQueryLiveData(HOT_STOCK_REF);

private final LiveData<HotStock> hotStockLiveData =
    Transformations.map(liveData, new Deserializer());

private class Deserializer implements Function<DataSnapshot, HotStock> {
    @Override
    public HotStock apply(DataSnapshot dataSnapshot) {
        return dataSnapshot.getValue(HotStock.class);
    }
}

@NonNull
public LiveData<HotStock> getHotStockLiveData() {
    return hotStockLiveData;
}
```

The utility class [`Transformations`](https://developer.android.com/reference/android/arch/lifecycle/Transformations.html) provides a static method [`map()`](https://developer.android.com/reference/android/arch/lifecycle/Transformations.html#map(android.arch.lifecycle.LiveData%3CX%3E,%20android.arch.core.util.Function%3CX,%20Y%3E)) that returns a new `LiveData` object given a source `LiveData` object and a [`Function`](https://developer.android.com/reference/android/arch/core/util/Function.html) implementation. This new `LiveData` applies the `Function` to every object emitted by the source, then turns around and emits the output of the `Function`. The `Deserializer` function here is parameterized by the input type `DataSnapshot` and the output type `HotStock`, and it has one simple job - deserialize a `DataSnapshot` into a `HotStock`. Lastly, we'll add a getter for this new `LiveData` that emits the transformed `HotStock` objects.

With these additions, the application code can now choose to receive updates to either `DataSnapshot` or `HotStock` objects. As a best practice, `ViewModel` objects should emit objects that are fully ready to be consumed by UI components, so that those components are only responsible for displaying data, not processing data. This means that `HotStockViewModel` should be doing all the preprocessing required by the UI layer. This is definitely the case here, as `HotStock` is fully ready to consume by the Activity that's populating the UI. Here's what the entire Activity looks like now:

```java
public class MainActivity extends
AppCompatActivity {
  private TextView tvTicker;
  private TextView tvPrice;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tvTicker =
      findViewById(R.id.ticker);
    tvPrice = findViewById(R.id.price);
    HotStockViewModel hotStockViewModel =
      ViewModelProviders.of(this).get(HotStockViewModel.class);
    `

        LiveData<HotStock> hotStockLiveData = hotStockViewModel.getHotStockLiveData();

 `
    hotStockLiveData.observe(this, new Observer() {
      @Override
      public void onChanged(@Nullable HotStock hotStock) {
        if (hotStock != null) {
          // update the UI here
          with values in the snapshot
          tvTicker.setText(hotStock.getTicker());
          tvPrice.setText(String.format(Locale.getDefault(), "%.2f",
            hotStock.getPrice()));
        }
      }
    });
  }
}
```

All the references to Realtime Database objects are gone now, abstracted away behind `HotStockViewModel` and `LiveData`! But there's still one potential problem here.

### What if a `LiveData` transformation is expensive? 
All `LiveData` callbacks to `onChanged()` run on the main thread, as well as any transformations. The example I've given here is very small and straightforward, and I wouldn't expect there to be performance problems. But when the Realtime Database SDK deserializes a `DataSnapshot` to a JavaBean type object, it uses reflection to dynamically find and invoke the setter methods that populate the bean. This can become computationally taxing as the quantity and size of the objects increase. If the total time it takes to perform this conversion is over 16ms (your budget for a unit of work on the main thread), Android starts dropping frames. When frames are dropped, it no longer renders at a buttery-smooth 60fps, and the UI becomes choppy. That's called "[jank](https://developer.android.com/topic/performance/vitals/render.html)", and jank makes your app look poor. Even worse, if your data transformation performs any kind of I/O, your app could lock up and cause an [ANR](https://developer.android.com/topic/performance/vitals/anr.html).

If you have concerns that your transformation can be expensive, you should move its computation to another thread. That can't be done in a transformation (since they run synchronously), but we can use something called `[MediatorLiveData](https://developer.android.com/topic/libraries/architecture/livedata.html#merge_livedata)` instead. `MediatorLiveData` is built on top of a map transform, and allows us to observe changes other `LiveData` sources, deciding what to do with each event. So I'll replace the existing transformation with one that gets initialized in the no-arg constructor for `HotStockViewModel` from part 1 of this series:

```java
private final FirebaseQueryLiveData liveData = new FirebaseQueryLiveData(HOT_STOCK_REF);
private final MediatorLiveData<HotStock> hotStockLiveData = new MediatorLiveData<>();

public HotStockViewModel() {
    // Set up the MediatorLiveData to convert DataSnapshot objects into HotStock objects
    hotStockLiveData.addSource(liveData, new Observer<DataSnapshot>() {
        @Override
        public void onChanged(@Nullable final DataSnapshot dataSnapshot) {
            if (dataSnapshot != null) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        hotStockLiveData.postValue(dataSnapshot.getValue(HotStock.class));
                    }
                }).start();
            } else {
                hotStockLiveData.setValue(null);
            }
        }
    });
}
```

Here, we see that `addSource()` is being called on the `MediatorLiveData` instance with a source `LiveData` object and an `Observer` that gets invoked whenever that source publishes a change. During `onChanged()`, it offloads the work of deserialization to a new thread. This threaded work is using [`postValue()`](https://developer.android.com/reference/android/arch/lifecycle/MutableLiveData.html#postValue(T)) to [update](https://developer.android.com/topic/libraries/architecture/livedata.html#update_livedata_objects) the `MediatorLiveData` object, whereas the non-threaded work when (dataSnapshot is null) is using [`setValue()`](https://developer.android.com/reference/android/arch/lifecycle/MutableLiveData.html#setValue(T)). This is an important distinction to make, because `postValue()` is the thread-safe way of performing the update, whereas `setValue()` may only be called on the main thread.

**NOTE: I don't recommend starting up a new thread like this in your production app.** This is not an example of "best practice" threading behavior. Optimally, you might want to use an `[Executor](https://developer.android.com/reference/java/util/concurrent/Executor.html)` with a pool of reusable threads ([for example](https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/AppExecutors.java)) for a job like this.

### There's still room for improvement! 
Now that we've removed Realtime Database objects from the Activity and accounted for the performance of the transformation from `DataSnapshot` to `HotStock`, there's still another performance improvement to make here. When the Activity goes through a configuration change (such as a device reorientation), the `FirebaseQueryLiveData` object will remove its database listener during `onInactive()`, then add it back during `onActive()`. While that doesn't seem like a problem, it's important to realize that this will cause another (unnecessary) round trip of all data under `/hotstock`. I'd rather leave the listener added and save the user's data plan in case of a reorientation. So, in the next part of this series, I'll look at a way to make that happen.

I hope to see you next time, and be sure to follow [@Firebase on Twitter](https://twitter.com/Firebase) to get updates on this series! You can click through to part 3 [right here](https://firebase.googleblog.com/2017/12/using-android-architecture-components_22.html).
