Offline-First

Offline-First: Combining Room, Retrofit and a Repository

In an offline-first app the local database is the single source of truth: the UI observes only Room 234 , the network only updates Room, and the screen follows through the Flow of Reactive Queries. Nothing waits for the network before drawing:

Offline-first: the UI reads only Room, and the network only writes to it
Offline-first: the UI reads only Room, and the network only writes to it

Two small changes complete the pattern. The repository exposes Room's Flow and a status built from the SyncState DataStore 234 of Proto DataStore, and the ViewModel shows the cache first, then refreshes without dropping back to a spinner:

ui/ViewModels.kt: cached rows first, then the network (excerpt)Kotlin
    viewModelScope.launch {                              // 5.27.8 cached rows first...
      repo.observeBooks().collect { if (it.isNotEmpty()) load.value = LoadState.Success(it) }
    }
    refresh()                                            // ...then ask the network
  ...
      if (load.value !is LoadState.Success) load.value = LoadState.Loading   // keep the cache

The interface gives observeBooks() and observeStatus() defaults (emptyFlow()), so Testing with Fake Dependencies's fake and tests still passed. With the test server stopped, a cold start logged:

Output of 158
I/OkHttp  : <-- HTTP FAILED: java.net.ConnectException: Failed to connect to /10.0.2.2:8616.
http://10.0.2.2:8616/books (490ms)
W/BookNestNet: offline: java.net.ConnectException: Failed to connect to /10.0.2.2:8616
D/BookNestVM: loaded: Success
BookNest with the test server running and after it was stopped: same books, covers from Coil's disk cache, and a status line from the SyncState store
BookNest with the test server running and after it was stopped: same books, covers from Coil 11,909 's disk cache, and a status line from the SyncState store

React Native's TanStack Query 79,069 cache (useQuery and Caching) approximates the same idea in JavaScript. Still missing: refreshing on a schedule (WorkManager 234 , Background Sync), and offline writes, which need a queue of pending changes and a conflict rule such as "last write wins".