Caching made simple on Android

Matthew Dolan
5 min readOct 30, 2017

Developing for the next billion users isn’t just about making your app as small as possible but also requires us to (re-)think our network connectivity.

With only 43% of the world having access to a 4G signal it’s easy to see why Google is pushing developers to optimise networking with their Connectivity for billions guidance.

An offline-first architecture initially tries to fetch data from local storage and, failing that, requests the data from the network. After being retrieved from the network, the data is cached locally for future retrieval.

The guidelines talk about deduplicating network requests with few instructions on how to achieve this other than a brief mention to use SQLite, SharedPreferences and DiskLruCache.

So, how do we go about achieving a caching mechanism where we can easily store data in memory and on disk whilst loading a cache miss from the network.

There was an excellent talk, Composable Caching in Swift by Brandon Kase, at iOSCon 2017 that covered this very subject. In this article I’m going to show how we can implement this on Android, allowing us to perform caching while following good coding principles such as the single responsibility principle.

At its simplest, a cache is nothing more than a key-value store with a getter and setter. Using Kotlin’s coroutines, we can load the data in the background and return it sometime in the future; Deferred is very similar to Java’s Future.

interface Cache<Key : Any, Value : Any> {
fun get(key: Key): Deferred<Value?>
fun set(key: Key, value: Value): Deferred<Unit>
}

A simplified example for caching in SharedPreferences might look like the following:

class SharedPrefsCache(private val sharedPreferences:
SharedPreferences) : Cache<String, String> {
override fun get(key: String): Deferred<String?> {
return async(CommonPool) {
sharedPreferences
.getString(key, null)
}
}

override fun set(key: String, value: String): Deferred<Unit> {
return async(CommonPool) {
sharedPreferences
.edit().let {
it.putString(key, value)
it.apply()
}
}
}
}

--

--

Matthew Dolan

Matt Dolan has been eating doughnuts and developing with Android since the dark days of v1.6.