Architecture Guidelines

Android Architecture Guidelines are a set of best practices and recommended architecture pattern by Android Team; on how to build testable and production-quality apps.

Persisting data

Most modern Android apps maintain a synchronization between local database and the web service, this is super useful for users which helps in using the app even if the device is offline. This is something which users have started to now-a-days expect in apps.

The same is stated in the Building for Billion guide and the guidelines shows how the data should flow between web and local database in the diagram below:

None
Data flow between Local Database and Web service

It states to first fetch the data from local database; if the data doesn't match a certain condition, then make the required network call based upon the "should fetch" condition and then save the fetched data into the local database on response.

Remember, your UI should always reflect based on the data in the database.

This is a very common use-case hence the Android Team already created a helper class called NetworkBoundResource.

Demystifying NetworkBoundResource

NetworkBoundResource is a plain class which does the job of data flow between local database and your web-service using the power of MediatorLiveData and the Resource class to send state and data upstream to the Activity or Fragment.

This class is extremely well made. It works exactly as shown in the data flow diagram above (in case the diagram was too much, see the flow below)

  1. Initially it sends event for loading
  2. Fetches the data from local database (Note: It can be empty too)
  3. Checks the condition in "shouldFetch"
  4. If false, then sends the data upstream from local database
  5. If true, it performs the required network call and fetch the data
  6. On response, the data is then saved into local database and this data and event is sent upstream

Problems with this Implementation

While the concept behind is solid and already an out of the box solution. I still had a few gripes with this.

  1. It was using LiveData as its output, which while great for consuming, doesn't provide the same degree of flexibility that Rx observable would have provided.
  2. The data would start fetching the moment this resource was initialized, so my plans for creating a global scope of the variable in my DataSource was down the drain.
  3. Updating the data through this resource wasn't supported. i.e. if I had a pull to refresh implemented, there was a way to tell this resource to go fetch the new data and store it like you normally would.

My Approach

With the above changes in mind, I have posted the

  1. The class now exposes data through either an Observable or a Single based on the required usecase.
  2. The data starts emitting when the user subscribes to Observable or if a Single call was made prior to subscribing to Observable
  3. Exposed a helpful function `fetchFromNetwork` which can be used to force fetch the data from the network, persist it in the DB and propagate the change to UI through original Observable if active.
  4. Also exposed a function `setValueCallback` which can be used to update the values manually. This also returns the most recent data as argument is available.
  5. Added some helpful callbacks to the class.
  6. And since this is designed to have a global scope, I added a helper method to clear the state, so that when logging out would flush the data.

Implementation

Let's look at a sample usage of this class to exactly understand how this class works.

NetworkBoundResource is an abstract class, hence when you create object of it you'll need to override the following methods

  • loadFromDb() — Contains the logic to get data from database (Like Room)
  • createCall() — Contains the logic to get data from web-service
  • saveCallResult() — Here we save the data fetched from web-service
  • processResult() — To map the data between the result and request.

Conclusion.

This is still an iterative solution as I have been adding to it, whenever I feel its missing something. I'll be more than happy to get some feedbacks and improvements to the classes.

Thanks