Repository Pattern: Your App's Single Source of Truth

The Repository Pattern acts as a mediator for your app's data, fetching from sources like a network or database. Use it to separate your UI from data-fetching logic, like caching. The footgun is putting business logic here; it's for data operations only.
WHY IT EXISTS: Apps need to get data from different places, like network APIs, local databases, or device storage. Directly calling these varied sources from the UI layer (ViewModels or Activities) creates a tangled, hard-to-maintain codebase that is difficult to test and modify.
THE MENTAL MODEL: A repository is like a librarian for your app's data. Your ViewModel asks the librarian for a piece of information, and the librarian figures out where to get it—from the main shelf (local database) or by ordering it from another library (network API). The ViewModel doesn't need to know or care about these details; it just gets the data it asked for.
HOW IT WORKS: A repository class exposes simple data access methods to the rest of the app, such as getUsers() or updateProfile(profile). Internally, these methods contain the logic to manage one or more data sources. For example, a getUsers() method might first check a local Room database for cached data. If the data is missing or stale, it then makes a network call using Retrofit, saves the fresh data back to the database for future use, and finally returns the result. This entire process is abstracted away from the caller.
WHEN TO USE IT: Use a repository whenever your app deals with data from multiple sources (e.g., network and local cache) or when you want to implement a caching strategy. It is a foundational component of modern Android architecture that decouples your data layer from the UI layer, making the app more modular, scalable, and testable. You can easily swap in a fake repository during unit tests to simulate different data scenarios.
WHEN NOT TO USE IT: For an extremely simple app that only reads from a single, non-cached source, a repository might feel like unnecessary boilerplate. However, since many apps eventually grow in complexity, starting with a repository is often a good practice that pays off later. The main reason to avoid it is if the added layer of abstraction provides zero benefit for your specific, trivial use case.
ONE CANONICAL EXAMPLE: A ViewModel calls userRepository.getUser(userId). The repository first checks its local Room database for that user. If the user data is less than five minutes old, it returns the cached data immediately. If not, it triggers a network call via a Retrofit service, updates the Room database with the fresh user data, and then returns that new data. The ViewModel receives the user data without ever knowing whether it came from the network or the local cache.
Read the original → developer.android.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.