-
Notifications
You must be signed in to change notification settings - Fork 0
Data flows
In this app I'm using a class called NetworkBoundResource
. Its described in Google's guide to app architecture.
The following diagram shows the decision tree for NetworkBoundResource:
It starts by observing the database for the resource. When the entry is loaded from the database for the first time,
NetworkBoundResource
checks whether the result is good enough to be dispatched or that it should be re-fetched from the network. Note that both of these situations can happen at the same time, given that you probably want to show cached data while updating it from the network.
If the network call completes successfully, it saves the response into the database and re-initializes the stream. If network request fails, the
NetworkBoundResource
dispatches a failure directly.
Actually in the Google's Guide they show kind of old and messy version of NetworkBoundResource
class without modern Kotlin features such as Flows.
Here's how the new and improved solution looks like.
inline fun <ResultType, RequestType> networkBoundResource(
crossinline query: () -> Flow<ResultType>,
crossinline fetch: suspend () -> RequestType,
crossinline saveFetchResult: suspend (RequestType) -> Unit,
crossinline shouldFetch: (ResultType) -> Boolean = { true }
) = flow {
val data = query().first()
val flow = if (shouldFetch(data)) {
emit(Resource.Loading(data))
try {
saveFetchResult(fetch())
query().map { Resource.Success(it) }
} catch (throwable: Throwable) {
query().map { Resource.Error(throwable, it) }
}
} else {
query().map { Resource.Success(it) }
}
emitAll(flow)
}
So, this approach allows app to work without Internet access as long as it has some cached data in the Room database. And it's working in combination with Glide library and its internal caching mechanism, so not only the data will appears on the screen but also the cached pictures.