Building an Offline first application

Vikas Bharti
Awesome Android
Published in
3 min readDec 8, 2018

Depths of building offline-friendly mobile applications. If you’re looking to understand read the full article.

When you are on blazing fast LTE networks, everything seems fluid and there’s hardly any issue. But the next billion people are on low bandwidth data connections. The real challenge is to build great experience for these users.

In general, apps work best when there is a fast data connection or WiFi.
Poor connectivity can result in a poor user experience. Apps with poor UX are frustrating, and many users may simply choose to delete them.

So, how can you make part of your app available without an internet connection?

How Do Most Apps Work?

Most apps use a simple cycle of data transfer, which includes the app on one side and the content from a server on the other side. These two should talk to each other to ensure a smooth transfer of data anytime it’s needed.

You might think that e-commerce apps or photo stocks need to be online all the time and might slow down whenever the internet connection is slow.

However, if the apps are “offline-first,” they will not slow down when connectivity is poor.

What’s the problem?

There is a common way to accomplish this by setting flags(isSync=false) for each row in mobile database and then fetch all non-updated rows and send those rows to server. Once It is synced, update(isSync=true) those rows in local DB. But this approach needs a lot of boilerplate code and required a lot of things needed to be taken care of.

Let’s find out an easy way

Here I am going to introduce a library developed by NYTimes. A Store is a class that simplifies fetching, parsing, storage, and retrieval of data in your application. Store provides a level of abstraction between UI elements and data operations.

A Store is responsible for managing a particular data request. When you create an implementation of a Store, you provide it with a Fetcher, a function that defines how data will be fetched over network. You can also define how your Store will cache data in-memory and on-disk, as well as how to parse it. Since Store returns your data as an Observable, threading is a breeze! Once a Store is built, it handles the logic around data flow, allowing your views to use the best data source and ensuring that the newest data is always available for later offline use. Stores can be customized to work with your own implementations or use our included middleware.

Store leverages RxJava and multiple request throttling to prevent excessive calls to the network and disk cache. By utilizing Store, you eliminate the possibility of flooding your network with the same request while adding two layers of caching (memory and disk).

How to include in your project

Add this line in your build.gradle(app)

implementation 'com.nytimes.android:store3:3.1.0'

How to configure a Store

Let’s start by looking at what a fully configured Store looks like. We will then walk through simpler examples showing each piece:

Store<ArticleAsset, Integer> articleStore = StoreBuilder.<Integer, BufferedSource, ArticleAsset>parsedWithKey().fetcher(articleId -> api.getArticleAsBufferedSource(articleId))  // OkHttp responseBody.source().persister(FileSystemPersister.create(FileSystemFactory.create(context.getFilesDir()), pathResolver))
.parser(GsonParserFactory.createSourceParser(gson, ArticleAsset.Article.class)).open();

With the above setup you have:

  • In-memory caching for rotation
  • Disk caching for when users are offline
  • Parsing through streaming API to limit memory consumption
  • Rich API to ask for data whether you want cached, new or a stream of future data updates.

And now for the details:

Creating a Store

You create a Store using a builder. The only requirement is to include a Fetcher<ReturnType, KeyType> that returns a Single<ReturnType> and has a single method fetch(key)

Store<ArticleAsset, Integer> store = StoreBuilder.<>key()
.fetcher(articleId -> api.getArticle(articleId)) // OkHttp responseBody.source().open();

Stores use generic keys as identifiers for data. A key can be any value object that properly implements toString(), equals() and hashCode(). When your Fetcher function is called, it will be passed a particular Key value. Similarly, the key will be used as a primary identifier within caches (Make sure to have a proper hashCode()!!).

What is Barcode

Barcode is used as a key for a particular store and it has two fields both of string types.

BarCode barcode = new BarCode("Article", "42");

When using a Barcode as your key, you can use a StoreBuilder convenience method

Store<ArticleAsset, BarCode> store = StoreBuilder.<ArticleAsset>barcode().fetcher(articleBarcode -> api.getAsset(articleBarcode.getKey(), 
articleBarcode.getType())).open();

Conclusion

It’s understandable that allowing an app to work offline ensures better UX, a leg up on the competition, and greater customer loyalty. So today we have learnt how to build an offline first application without any hassle and boilerplate code. Good luck!

--

--

Vikas Bharti
Awesome Android

Solving Tech Problems | Android | iOS | Exp. over 8 yrs | Believer