Android Data Layer & Offline-First
Instructions
The Data Layer coordinates data from multiple sources.
- Repository Pattern
-
Role: Single Source of Truth (SSOT).
-
Logic: The repository decides whether to return cached data or fetch fresh data.
-
Implementation: class NewsRepository @Inject constructor( private val newsDao: NewsDao, private val newsApi: NewsApi ) { // Expose data from Local DB as the source of truth val newsStream: Flow<List<News>> = newsDao.getAllNews()
// Sync operation suspend fun refreshNews() { val remoteNews = newsApi.fetchLatest() newsDao.insertAll(remoteNews) } }
- Local Persistence (Room)
-
Usage: Primary cache and offline storage.
-
Entities: Define @Entity data classes.
-
DAOs: Return Flow<T> for observable data.
- Remote Data (Retrofit)
-
Usage: Fetching data from backend.
-
Response: Use suspend functions in interfaces.
-
Error Handling: Wrap network calls in try-catch blocks or a Result wrapper to handle exceptions (NoInternet, 404, etc.) gracefully.
- Synchronization
-
Read: "Stale-While-Revalidate". Show local data immediately, trigger a background refresh.
-
Write: "Outbox Pattern" (Advanced). Save local change immediately, mark as "unsynced", use WorkManager to push changes to server.
- Dependency Injection
- Bind Repository interfaces to implementations in a Hilt Module. @Binds abstract fun bindNewsRepository(impl: OfflineFirstNewsRepository): NewsRepository