In the past, Android developers struggled with bloated Activities and Fragments. Then MVVM, MVI, and Jetpack Compose helped us push presentation logic into ViewModels, business logic into UseCases, and data handling into Repositories — making the UI layer thin and reactive.
But a new problem has quietly emerged: we still tie ViewModels to entire screens, exposing the whole screen state and handling all user intents. As screens grow more complex, ViewModels become longer, harder to test, and harder to maintain.
What if we had multiple ViewModels per screen, each tied to a smaller UI component? This leads to two important questions that haven't been answered yet:
- Where do you hold the common state that multiple UI components of a screen might need?
- How can ViewModels communicate with each other when one needs to update the UI state that another ViewModel observes?
Repositories aren’t the answer — they expose domain models and shouldn’t know anything about the UI. Other state holder patterns that have been proposed do not fully address this problem either — they typically manage global or domain state, and they aren't designed to coordinate shared, screen-specific UI state across multiple ViewModels. Clearly, there’s a missing piece in our architecture.
Introducing the Mediator Pattern — a pattern that allows you to break a large ViewModel into smaller ones by moving the screen-specific UI state into a Mediator, with each smaller ViewModel deriving and updating only the part it needs.
Join this session to see the pattern applied in a real-world Android app and learn how to:
- Break a large ViewModel into smaller, independently testable ViewModels, each tied to a smaller component of the screen.
- Enable the smaller, screen-scoped ViewModels to reactively communicate with each other through a shared Mediator.
- Use Hilt or Koin to scope the Mediator to the screen’s lifecycle, automatically disposing it when the user exits that screen.
Whether you’re working with Jetpack Compose or traditional Views, this talk will give you the missing piece your architecture needs — so you can grow your apps without growing complexity.