Neat Android Architecture through NetworkBoundResource

| Colin Dodd

One of the joys of working at Bakken & Bæck is that you regularly get the chance to click "New Project" in Android Studio. Last time I got to do that, it was decided that we'd do things using Googles Architecture Components. Rx was out; LiveData was in.

This isn't going to be a piece comparing the two technologies. Instead I am going to talk about a small utility class NetworkBoundResource and how it can help you architect your apps.

In keeping unopinionated about how to implement architecture, NetworkBoundResource isn't even a part of the Android framework despite being mentioned in the official guide to app architecture. Instead it exists as part of the samples repo for architecture components.

So, what does it do?

Simply, it allows you to return data from database whilst simultaneously fetching the latest data from the network. When the network call is returned, the result can be stored to database and the new result can be broadcast.

To put that in more concrete terms; say you have an app that fetches the weather for the users current location. The first time the user opens the app there is obviously nothing in the database, so you'll need to request the latest weather information from the network. Once you've fetched the weather information you can show it to the user.

It makes sense to cache that weather information to a database. The next time the user requests the weather information it can then be read from the database. This avoids a network call and works offline.

However, the weather obviously changes so if your user is always seeing the weather thats cached in the database your app isn't going to be very useful. You'll want to add some logic that decides how long the information in the database should be considered fresh. Once the information is no longer fresh a new network call can be started to get the latest weather information.

Network calls can fail, or be slow, so ideally you'll also show the old weather information whilst the network call is happening. When the network call is complete the cached information can be replaced with the latest information and the UI can be refreshed.

All of this logic makes for an app that works offline, feels quick, and is kept up to date. NetworkBoundResource will give you all of this functionality and all it requires is the implementation of 4 methods:

  • loadFromDb is used to return whatever information is stored in the database.
  • shouldFetch decides whether the cached data is fresh or not. If not a new network request will be triggered.
  • createCall creates the network request. NetworkBoundResource will take responsibility for triggering the request.
  • saveCallResult saves the network response into the database. Any mapping of the response into a model object before storing can be done here.

For more concrete implementation details check the section on exposing network status in the official app architecture guide.

Under the hood

NetworkBoundResource works by making use of MediatorLiveData. In essence MediatorLiveData can observe multiple LiveData objects and react to their changes. In this instance there are two LiveData sources; one for the database and one for the network. Both of those LiveData are wrapped into one MediatorLiveData and it is that which is exposed by NetworkBoundResource. More information about MediatorLiveData can be found in the Arch documentation