Migrating Architecture Blueprints to Jetpack Compose

As part of our effort to modernize the app architecture guidance, we want to experiment with different UI patterns to see what works best, find similarities and differences between the alternatives, and ultimately consolidate those learnings as best practices.
To make our findings as easy to follow as possible, we needed a sample that has a familiar business case and isn’t too complicated. And… who doesn’t know about TODO apps? We chose Architecture Blueprints! Historically, Blueprints served as an experimental playground for architecture choices. What a great fit for this as well!

The patterns we want to experiment with are obviously affected by the different APIs available nowadays. The new kids in town are Jetpack Compose’s State APIs! As Compose seamlessly works with any Unidirectional Data Flow pattern, we’ll use Compose to render UI to make a fair comparison.
This blog post tells the story of how the team migrated Architecture Blueprints to Jetpack Compose. As LiveData is also considered an alternative in our experiments, we left the sample as it was at the time of the migration. In this refactoring, the ViewModel classes and the data layer were left untouched.
⚠️ The architecture used in this LiveData-based codebase doesn’t fully follow the latest architecture best practices. In particular, LiveData shouldn’t be used in the data or domain layers — Flows and coroutines should be used instead.
Now that the context is clear, let’s dive in on how we approached refactoring Blueprints to Jetpack Compose. You can check out the full code on the main branch.
The goal of a gradual migration is to ease code reviews and maintain a shippable product throughout the migration. The migration plan involved three steps:
Migrate the content of each screen to Compose. Each screen could be individually migrated to Compose, including their UI tests. Fragments then become the container/host of each migrated screen.
Migrate the app to Navigation Compose — which removes all Fragments from the project — and migrate the Activity UI logic to root composables. End-to-end tests are also migrated at this point.
Remove View system dependencies.



