Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Modern Architecture Patterns


1. MVVM Architecture

Q: Explain MVVM architecture and why we use it in Android.

MVVM (Model-View-ViewModel) separates an application into three layers:

LayerResponsibilityAndroid Components
ModelData and business logicRepository, Data Sources, Room, Retrofit
ViewDisplay UI, capture user inputActivity, Fragment, Composable
ViewModelHold UI state, expose data to ViewJetpack ViewModel

Q: Why is MVVM the recommended pattern?

  1. Separation of Concerns: Each layer has a single responsibility
  2. Testability: ViewModel can be unit tested without Android framework
  3. Lifecycle Awareness: ViewModel survives configuration changes
  4. Maintainability: Changes in one layer don’t cascade to others

Q: What are common MVVM mistakes?

  • Passing Activity/Fragment to ViewModel: Causes memory leaks
  • Holding View references in ViewModel: Same leak issue
  • Business logic in View: Should be in ViewModel or Use Cases
  • ViewModel importing android. packages*: Breaks testability (lifecycle components excepted)

Q: What’s the Single UI State pattern?

Instead of multiple LiveData/StateFlow for different UI elements, use one sealed class representing all possible screen states. This prevents impossible state combinations and makes reasoning about UI easier.


2. MVI Architecture

Q: Explain MVI and when to use it over MVVM.

MVI (Model-View-Intent) enforces unidirectional data flow:

  • Intent: User actions or events (ButtonClicked, TextChanged)
  • Model: Complete, immutable UI state at any moment
  • View: Renders state, emits intents

The flow is circular: User Action → Intent → Reducer → New State → View Update

Q: MVVM vs MVI comparison?

AspectMVVMMVI
StateMultiple StateFlowsSingle ViewState
ComplexityLowerHigher boilerplate
PredictabilityGoodExcellent (single source of truth)
DebuggingModerateEasy (log all state changes)
Best ForSimple-medium appsComplex interactions, forms

Q: When to use MVI?

  • Complex multi-step workflows
  • Forms with interdependent validation
  • Need to track/debug all state changes
  • Time-travel debugging requirements
  • State consistency is critical (financial, healthcare apps)

Q: Describe the layered architecture Google recommends.

Three layers with clear dependencies (outer layers depend on inner):

UI Layer (Presentation)

  • UI elements: Activities, Fragments, Composables
  • State holders: ViewModels
  • Observes state, forwards events

Domain Layer (Optional)

  • Use Cases / Interactors
  • Contains reusable business logic
  • Combines data from multiple repositories

Data Layer

  • Repositories: Single source of truth for each data type
  • Data Sources: Remote (API), Local (Room), Cache

Q: What are the key principles?

  1. Separation of Concerns: UI shouldn’t know about data sources
  2. Drive UI from Data Models: UI reflects state, doesn’t own it
  3. Single Source of Truth (SSOT): One owner per data type
  4. Unidirectional Data Flow: State flows down, events flow up

Q: When is the Domain layer needed?

  • Business logic reused across multiple ViewModels
  • Complex data transformations or combinations
  • Need to enforce business rules consistently
  • Large teams where clear boundaries help

4. Repository Pattern

Q: What is the Repository pattern and why use it?

Repository is an abstraction over data sources. It:

  • Decides whether to fetch from network or cache
  • Handles caching strategies
  • Transforms DTOs to domain models
  • Provides a clean API to the rest of the app

Q: What caching strategies are common?

StrategyBehaviorUse Case
Cache FirstReturn cache, then refreshNews feeds, social content
Network FirstTry network, fallback to cacheCritical data, payments
Cache OnlyNever hit networkOffline-first apps
Network OnlyNever cacheSensitive data

Q: How do you expose data from Repository?

Use Flow for observable data streams. The Room DAO returns Flow, Repository exposes it, ViewModel collects it. Changes propagate automatically from database to UI.


5. Clean Architecture

Q: How does Clean Architecture relate to Android?

Clean Architecture organizes code in concentric circles:

  • Entities (innermost): Business objects, pure Kotlin
  • Use Cases: Application-specific business rules
  • Interface Adapters: ViewModels, Repositories, Presenters
  • Frameworks (outermost): Android, Room, Retrofit

The Dependency Rule: Dependencies point inward. Inner layers know nothing about outer layers.

Q: What are the benefits?

  • Business logic is completely isolated from frameworks
  • Easy to test core logic without Android dependencies
  • Can swap frameworks (e.g., Retrofit → Ktor) without touching business logic
  • Forces clear separation and single responsibility

Q: What are the drawbacks?

  • More boilerplate (mappers, interfaces, multiple models)
  • Can be overkill for simple apps
  • Learning curve for the team
  • Need discipline to maintain boundaries

6. State Management

Q: LiveData vs StateFlow vs SharedFlow?

TypeHot/ColdLifecycle AwareInitial ValueReplay
LiveDataHotYes (automatic)OptionalLatest
StateFlowHotNo (need repeatOnLifecycle)RequiredLatest
SharedFlowHotNoNot requiredConfigurable

Q: When to use each?

  • LiveData: Simple cases, team familiar with it, automatic lifecycle handling
  • StateFlow: UI state, need .value access, Compose integration
  • SharedFlow: One-time events (navigation, toasts), multiple subscribers

Q: How do you handle one-time events in MVVM?

Options:

  1. Channel + receiveAsFlow(): Consumed exactly once
  2. SharedFlow with replay=0: Events don’t replay to new subscribers
  3. Event wrapper class: Wrap value, mark as consumed

Avoid using StateFlow for events—new subscribers receive the last event again.


7. Dependency Injection in Architecture

Q: How does DI fit into the architecture?

DI provides dependencies to each layer:

  • ViewModel receives Repository and Use Cases
  • Repository receives DataSources
  • DataSources receive Retrofit, Room, etc.

This enables:

  • Swapping implementations (real vs fake for testing)
  • Scoping (singleton, per-screen, per-ViewModel)
  • Lazy initialization

Q: What scopes are common in Android DI?

ScopeLifecycleExample
SingletonApp lifetimeRetrofit, OkHttp, Room Database
Activity/FragmentScreen lifetimeScreen-specific analytics
ViewModelViewModel lifetimeUse Cases with state

Quick Reference

PatternKey Insight
MVVMViewModel holds UI state, survives config changes, never references View
MVISingle immutable state, unidirectional flow, great for complex UIs
Layered ArchitectureUI → Domain (optional) → Data; dependencies point inward
RepositoryAbstracts data sources, handles caching, single source of truth
Clean ArchitectureBusiness logic independent of frameworks; more structure, more boilerplate
State ManagementStateFlow for state, Channel/SharedFlow for events, avoid LiveData for new code