Android: Single Source Of Truth Strategy (Offline-First)

4 min readFeb 15
Photo by Marc Beuret on Unsplash

As suggested by the name, with single source of truth strategy we are defining a place where to find and store our data, being sure that there is just one source accessible to the rest of our app. Also, it helps us to have a version of our data available offline.

Single Source Of Truth

This pattern centralizes all the data in one place, in our case a database implemented with Room (you can follow the guide in the official guideline to set your database).

First, we should observe the database checking if there are local data available, if yes we should show them and in the other case we should check if it is necessary to fetch for new data from network or not, it depends of course if it’s necessary to update the local data that we have saved on our database, or if by chance our database is currently empty.

In the case of outdated/empty data, we should fetch data from network (remote data), if the call has success we can update our database with the remote data and show the local data already update, in the other case we should show an error.

Result wrapping

Before to show a possible implementation, a little parenthesis about how to wrap our data in a sealed class Result:

sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val errorMessage: String, val throwable: Throwable) : Result<Nothing>()

This class help us to handle a Success or an Error scenario, we use a method with a runCatching to wrap the result:

suspend fun <T> getResult(invoke: suspend () -> T): Result<T> = runCatching {
}.getOrElse {
Result.Error("Error message", it)


internal fun singleSourceOfTruthStrategy(
readLocalData: suspend () -> List<Beer>,
readRemoteData: suspend () -> List<Beer>,
saveLocalData: suspend (List<Beer>) -> Unit,
): Flow<Result<List<Beer>>>