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