Explain ViewModel, Repository, and Data Source in MVVM

This tests your understanding of separation of concerns. A great answer defines ViewModel (UI state), Repository (data abstraction), and Data Sources (implementation), then explains the unidirectional data flow.
WHAT THIS TESTS: This question assesses your grasp of separation of concerns, a core principle of modern software architecture. The interviewer wants to see if you understand not just the definition of each MVVM component, but WHY they are separated. A senior-level answer focuses on how this structure creates a testable, maintainable, and lifecycle-aware application by enforcing a unidirectional data flow and establishing a single source of truth.
A GOOD ANSWER COVERS: First, define the distinct roles. The ViewModel is a lifecycle-aware UI state holder; it prepares and manages data for the UI and survives configuration changes. The Repository acts as the single source of truth for a specific type of data, abstracting its origin. Data Sources are the concrete implementations for fetching or saving data, like a Room DAO for local database access or a Retrofit service for network calls.
Second, explain the interaction flow. The UI (Activity/Fragment) observes data exposed by the ViewModel (usually via StateFlow or LiveData). The ViewModel never accesses data sources directly; instead, it requests data from the Repository. The Repository contains the logic to decide where to get the data from—for example, fetching from a local cache (Room) first, and only calling the remote data source (Retrofit) if the cache is empty or stale.
Third, highlight the benefits. This separation makes each layer independently testable. You can unit test a ViewModel with a fake Repository, and unit test a Repository with fake data sources. It also decouples the UI from the data layer, simplifying UI logic.
COMMON WRONG ANSWERS: A major red flag is describing the ViewModel as directly calling Retrofit or a Room DAO. This completely misses the point of the Repository pattern, which is to abstract these implementation details. This makes the ViewModel brittle and hard to test.
Another common mistake is having the UI (Activity/Fragment) directly reference the Repository. This bypasses the ViewModel's critical role in state management and lifecycle handling, leading to data being lost on configuration changes and potential memory leaks.
Simply defining the components without explaining the data flow or the benefits of the separation indicates a junior-level understanding.
LIKELY FOLLOW-UPS: "How would you handle a user action, like a button click to refresh data, in this architecture?" (UI calls a method on the ViewModel, which then calls a refresh method on the Repository).
"How do you handle network errors?" (The Repository should catch exceptions from the data source and wrap the result in a sealed class like Result<T>, which flows up to the ViewModel to be mapped into a specific UI error state).
"Where would you put business logic that combines data from two different repositories?" (In a UseCase/Interactor class that sits between the ViewModel and the Repositories).
ONE CONCRETE EXAMPLE: For a user profile screen, the ProfileViewModel exposes a StateFlow<ProfileUiState>. On initialization, it calls userRepository.getProfile(userId). The UserRepository first checks its local data source, UserDao (Room), for the profile. If the data is stale (e.g., cached more than 15 minutes ago), it calls the remote data source, UserApiService (Retrofit), to fetch a fresh profile. It then saves the new data back into Room and returns the updated profile. This data flows back to the ViewModel, which updates its UI state, causing the UI to automatically re-render with the new information.
Source: developer.android.com
Read the original → developer.android.com
- #android
- #mvvm
- #architecture
- #kotlin
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.