Implement Android Repository Pattern
AI skill for implementing the Android Repository Pattern - Room/Retrofit data sources, caching, Hilt DI, and coroutine flows.
Why it matters
Implement robust and scalable data layers for Android applications using the Repository Pattern. This asset provides expert guidance and code examples for managing data sources, ensuring a single source of truth, and optimizing data retrieval.
Outcomes
What it gets done
Design and implement repository interfaces and data source abstractions.
Integrate local (Room) and remote (Retrofit) data sources.
Apply Network Bound Resource and Resource Wrapper patterns.
Configure dependency injection with Hilt for seamless integration.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-android-repository-pattern | bash Overview
Android Repository Pattern Expert Agent
Implements the Android Repository Pattern - Room and Retrofit data sources, layered caching, Hilt dependency injection, and coroutine-based reactive flows. Use when structuring an Android app's data layer for offline-first behavior with coordinated local caching and network sync.
What it does
This skill provides expertise in implementing the Repository Pattern for Android applications, covering modern Android architecture, data layer design, dependency injection, coroutines, and multi-source data integration across local databases, remote APIs, and caching strategies. Core principles center on a single source of truth: the repository acts as the sole data access point, abstracting data sources from the UI layer, coordinating between sources and caching logic, and exposing a clean API to ViewModels and use cases. Data source abstraction separates local sources (Room, SharedPreferences, files), remote sources (REST/GraphQL APIs), in-memory caching for performance, and an offline-first approach with sync capability.
The repository architecture defines local and remote data source interfaces plus a repository interface exposing a Flow of wrapped results. The Network Bound Resource pattern implements this by emitting a Loading state, then cached local data immediately, then fresh network data once fetched - writing successful network responses back to the local cache - all wrapped in a sealed Resource type (Success/Error/Loading) and a sealed ApiResponse type for the network layer. Data source implementation covers a Room-backed local data source (DAO with query/insert operations) and a Retrofit-backed remote data source (API service interface with proper success/error handling on HTTP responses).
Dependency injection setup uses Hilt modules to bind repository and data source interfaces to their implementations, and provide singleton instances of the API service and DAO. Advanced patterns include a cached repository with a layered cache-check strategy (in-memory LRU cache first, then a time-based cache-expiry check against the local database, then network as a last resort, updating both the memory cache and cache timestamp on a network fetch) and repository testing with mocked data sources verifying the Loading-then-cached-then-network emission sequence. Performance optimization tips include using Flow for reactive UI updates, scoping coroutines properly with Dispatchers.IO for database/network work, size-limited in-memory caching, database triggers/observers for real-time sync, pagination for large datasets, distinctUntilChanged() to prevent redundant UI updates, StateFlow/SharedFlow as a single source of truth, proper error handling with retry mechanisms, database transactions for bulk operations, and WorkManager-based background sync for offline scenarios.
When to use - and when NOT to
Use this skill when structuring an Android app's data layer around the Repository Pattern - coordinating Room, Retrofit, and caching behind a clean API for ViewModels. It is well suited to apps needing offline-first behavior with a local cache and network sync. It is not meant for trivial apps with a single, simple data source where the abstraction layer adds unnecessary complexity.
Inputs and outputs
Input: the app's data sources (local database schema, remote API) and caching/offline requirements.
Output: repository interfaces and implementations, local/remote data source implementations, Hilt DI modules, and repository tests. Example Network Bound Resource pattern:
override fun getUsers(): Flow<Resource<List<User>>> = flow {
emit(Resource.Loading())
val localUsers = localDataSource.getUsers()
emit(Resource.Success(userMapper.mapEntitiesToDomain(localUsers)))
val networkUsers = remoteDataSource.fetchUsers()
when (networkUsers) {
is ApiResponse.Success -> {
val entities = userMapper.mapDtosToEntities(networkUsers.data)
localDataSource.insertUsers(entities)
emit(Resource.Success(userMapper.mapEntitiesToDomain(entities)))
}
is ApiResponse.Error -> emit(Resource.Error(networkUsers.message))
}
}.flowOn(Dispatchers.IO)
Integrations
Builds on Room for local persistence, Retrofit for remote APIs, Hilt for dependency injection, and Kotlin Coroutines/Flow for reactive data streams.
Who it's for
Android developers structuring the data layer with the Repository Pattern, and teams building offline-first apps that need coordinated local caching and network sync behind a clean, testable API.
FAQ
Common questions
Discussion
Questions & comments ยท 0
Sign In Sign in to leave a comment.