networkBoundResource
Creates a network-bound resource flow that implements the offline-first pattern.
This function creates a Flow that:
First queries the local database and emits cached data
Decides whether to fetch from network based on
shouldFetchpredicateIf fetching, emits Loading state with cached data
Fetches from network, saves to database, and emits updated data
On error, emits Error state with cached data still available
This pattern ensures your UI always has data to display (when available) even during network requests or when offline.
Usage Example
// In a Repository
override fun getUsers(): Flow<Resource<List<User>>> = networkBoundResource(
query = {
// Observe local database
localDataSource.observeUsers()
},
fetch = {
// Fetch from network API
networkDataSource.getUsers()
},
saveFetchedResult = { networkUsers ->
// Save network response to local database
localDataSource.saveUsers(networkUsers.map { it.toEntity() })
},
shouldFetch = { cachedUsers ->
// Fetch if cache is empty or stale
cachedUsers.isEmpty() || isCacheStale()
}
)Advanced Example with Timestamp-Based Caching
override fun getArticles(): Flow<Resource<List<Article>>> = networkBoundResource(
query = { localDataSource.observeArticles() },
fetch = { networkDataSource.getArticles() },
saveFetchedResult = { articles ->
localDataSource.saveArticles(articles, fetchedAt = System.currentTimeMillis())
},
shouldFetch = { cachedArticles ->
val cacheAge = System.currentTimeMillis() - cachedArticles.firstOrNull()?.fetchedAt ?: 0
cachedArticles.isEmpty() || cacheAge > 5.minutes.inWholeMilliseconds
}
)Network-Only (No Cache)
// If you don't want caching, use empty query and save
override fun getCurrentWeather(): Flow<Resource<Weather>> = networkBoundResource(
query = { flowOf(null) },
fetch = { weatherApi.getCurrentWeather() },
saveFetchedResult = { /* no-op */},
shouldFetch = { true } // Always fetch
)Return
A Flow emitting Resource states throughout the operation lifecycle: - Resource.Loading(cachedData) - when fetch starts (if shouldFetch returns true) - Resource.Success(freshData) - when data is successfully fetched and saved - Resource.Error(cachedData, error) - if fetch fails (cached data still available) - Resource.Success(cachedData) - if shouldFetch returns false
Parameters
The type of the data from the local database (what UI consumes).
The type of the data from the network API (may differ from ResultType).
Function that returns a Flow of cached data from the local database. This Flow will be observed and emitted throughout the resource lifecycle.
Suspend function that fetches fresh data from the network. Should throw exceptions on failure (will be caught and converted to Error state).
Suspend function that saves the fetched network data to local storage. Called before emitting the updated query results.
Predicate that determines whether to fetch from network based on cached data. Defaults to true (always fetch). Common patterns: - { it.isEmpty() } - fetch only if cache is empty - { it.isEmpty() || isStale(it) } - fetch if empty or stale - { true } - always fetch (refresh on every call) - { false } - never fetch (local-only)
See also
For detailed information about Resource states