This weblog sequence covers a “frequent UI first” migration technique of a View pattern to Jetpack Compose, guiding you thru the steps, with interop and kind issue assist, and why you may take into account an analogous strategy in your Compose migration.
Most of you might be most likely accustomed to Jetpack Compose and its advantages (simplifies-and-accelerates-UI-Android-development-with-less-code-powerful-tools-and-intuitive-Kotlin 🎶), so we received’t discuss this. In the event you’re in a position to begin anew and create a Compose-only app, you’re heading in the right direction. However then, this weblog won’t be for you :).
Whereas Compose-only is a dream expertise, the fact is that current apps shall be blended Views and Compose for a very long time. Actually, the commonest Compose migration technique we’ve seen amongst apps is: all new options and screens written in Compose, whereas previous code stays in Views. Relying on capacities, builders refactor previous code as properly. Nevertheless it’s not a should.
That is vital when deciding to start out migrating to Compose. You don’t want a Compose-only app to reap the advantages of Compose. Combined View and Compose code can work collectively and the earlier you introduce Compose, the simpler your upkeep shall be in the long term.
The way forward for Android UI is Compose-only. However the current requires Compose interop with Views.
With that in thoughts, let’s embark on a journey of migrating a View pattern with out going all the best way to 100% Compose to check interop capabilities, and some extra assumptions. To see a 100% Compose migration, take a look at Migrating Sunflower to Jetpack Compose.
The place to begin is our pattern protagonist Reply which is View-based and utilizing Materials 2. The hypotheses to check throughout this migration have been:
Testing the “Migration of frequent UI first” technique
Chances are high you’re working in a staff, in order everyone knows, parallelizing growth is essential for effectivity and minimizing duplicate work. This migration reveals that frequent UI elements, shared UI code or, on a bigger scale, design techniques may be migrated first, with minimal to no modifications tonon-UI layers. This unblocks parallel migration of whole screens and options.
You’ve got 2 attainable approaches:
- Preserve the View elements in parallel to the brand new Compose design system, primarily sustaining two design techniques
- Migrate solely to a single Compose design system, and whereas doing so, regularly replace current View code to make use of these new elements
For the targets of this pattern, we selected emigrate all frequent UI and use it in current View code.
Be aware: As Compose is an unbundled framework, including it for the primary time has a loading value. For extra info, see the Why do you have to all the time check Compose efficiency in launch? weblog submit. Use Macrobenchmarks to measure efficiency and make an knowledgeable choice between the 2 choices above.
Testing interop capabilities
Our check topic is an aged pattern, so it received’t be getting new options. Due to this fact, we opted to migrate current screens to Compose, relatively than undertake Compose for brand spanking new screens, as each approaches check the Compose and View interop capabilities. Validating the facility of interop reveals that refactoring previous code just isn’t a should and that incremental migration to Compose works properly. You’ll be able to if you wish to — nevertheless it’s not a necessity and you may depend on interop.
Migrating to Compose whereas retaining the unique navigation structure
This migration reveals that you would be able to hold utilizing Jetpack Navigation or a customized navigation setup, even for screens which can be solely Compose, making incremental migration to Compose much less work. Utilizing Navigation Compose isn’t a requisite to make use of Jetpack Compose.
Redesigning a characteristic/display screen? Good time emigrate to Compose!
If a serious redesign of a characteristic or a display screen is incoming, this is perhaps an excellent time to board the Compose prepare. You’ll have to do some rewriting anyway, so why not take this chance and do it with Compose?
Migrating to Compose? Good time so as to add kind issue assist!
This migration reveals how easy it’s to introduce assist for kind components when you begin utilizing composable components and screens, and it gives suggestions and steerage on adopting the fitting kind components mindset from begin.
Views to Compose don’t all the time want a 1:1 mapping
In the event you’ve used one element in Views, you won’t want the identical element in Compose. Benefit from migration to rethink the implementation of your components — change them or simplify them, if wanted. This pattern reveals examples of how one can change from, for instance, View ConstraintLayout
s to Compose Row
s and Column
s as a substitute.
Reply is an aged pattern. It’s a easy e mail app, with fundamental performance of displaying emails, filtering, organizing, and navigating between screens. It consists of Search, Residence, E mail and Compose (composing an e mail) screens.
Be aware: There’s a newer Reply model, with Compose and M3, as a part of our official Compose samples.
As with most samples, it focuses on showcasing a singular idea — on this case the Materials elements — and simplifies the remainder. So that you may discover it doesn’t have a ViewModel
, however relatively a simulation of enterprise logic within the EmailStore
. It additionally doesn’t have any exams 😬. This makes it fairly totally different from a manufacturing app (hopefully!). However as samples are oversimplified by design, this must do.
Be aware: Reply makes use of M2. Fairly than migrating to Compose and M3 on the similar time, we selected to separate it into two duties to promote an incremental and protected migration course of. Reply M3 migration is deliberate for a V2 sequel, together with navigation and animation. Nevertheless, we encourage you to pair Compose with M3 to unlock its full potential.
This log follows the steps we took when migrating Reply. Nevertheless, everybody’s free to decide on their very own path! Use this as a information, relatively than a rule e-book:
Step 0: Migration prep [in this post]
Step 1: Dependencies and theming [in this post]
Step 2: Smallest frequent UI elements [in this post]
Step 3: Migration of extra advanced elements [in part 2]
Step 4: Migration of low danger screens [in part 2]
Step 5: Migration of extra advanced screens [in part 2]
Step 0: Migration prep
🗒️ Duties:
- Learn migration documentation
- Analyze and check the app
- Confirm Compose stipulations
- Divide and conquer the workload
Learn migration documentation
“A starting is the time for taking probably the most delicate care that the balances are appropriate”, Frank Herbert mentioned correctly. That means — it’s vital to do your preparation properly, earlier than truly beginning. Migrating from Views to Compose generally is a mammoth activity — it takes time, and it is best to prioritize security and incrementation over pace. Presuming you’ve fundamental data of Compose, the next supplies make an excellent migration starter pack:
Confirm Compose stipulations
Guarantee that your app is in an excellent place for Compose migration. Think about the next necessities:
- Is it making use of or outfitted to use UDF? ✅
- Are there any structural blockers — e.g., minSdk<21, not utilizing Kotlin 😳? ❌
- Are any of your frameworks (testing, navigation and so forth.) too tightly coupled with View APIs? ❌
In addition to the optionally available, nice-to-haves:
- Is the app following the greatest structure practices? ✅
- How good is your staff’s data of fundamental Compose? ✅ 😎
- Do you’ve the time and sources for the educational curve? ✅
For Reply, nothing required drastic modifications earlier than including Compose.
Divide and conquer the workload
You need the preliminary migration steps to unblock others ASAP to allow them to develop new options and screens in Compose. For that, you want a plan for migrating the frequent UI first — whether or not it’s a part of a grander design system, in a standard UI module, or just stacked in a separate folder. That is the bottom-up migration technique.
In Reply, there are solely two shared lessons in ui/frequent
, so we used slightly creativeness and migrated some further ones — elements outfitted to be included in one other XML format or reused through its binding. Play faux for the sake of the tip objective 🙂.
Now that now we have studied, analyzed, and provide you with a plan, it’s time to start out coding.
Each migration step has an MVP participant and a professional tip.
🏅 MVP participant: Screenshot testing. An important factor to facilitate, as migration from Views to Compose might convey some difficult-to-catch UI regression. To be taught extra about Compose and screenshot testing, check out how this was added to Now in Android.
💎 Professional tip: One other nice alternative for Compose migration is when there’s an incoming redesign of a characteristic, display screen, or large chunk of elements. And if all this rewrite work is being accomplished, why not get the extra good thing about introducing kind components assist?
Step 1: Dependencies and theming
🗒️ Duties:
- Add dependencies
- Migrate theme
First code change is including Compose dependencies 😅. The Compose setup web page has all the data you want.
Theming would typically be the second code change. Since organising theming is fundamental Compose data, we initially determined to make use of the mdctheme
adapter to rapidly maps the XML theming to a corresponding Compose one. Nevertheless, the adapter has since been deprecated and our steerage now recommends organising the M2 theming manually, following the Compose M2 theming codelab.
Be aware: Materials 3 is our really helpful design system. See Migrate XML themes to Compose and the right way to use the Materials 3 Theme Builder for extra info.
💻 This step consists of two PRs, accomplished at totally different instances:
Step 1 — Compose dependencies [With the mdctheme
adapter code]
Step 1.2 — M2 theming setup [Removal of deprecated mdctheme
adapter and manual setup of M2 theme]
🏅 MVP participant: Materials 3 Theme Builder. This device helps you visualize Materials dynamic colour, simply create a customized M3 theme, and export it to code.
💎 Professional tip: A protected and incremental Compose migration follows this order:
- Smallest frequent elements first
- Scale to extra advanced frequent elements
- Low-risk, low-complexity screens and options
- Scale to high-engagement screens and options
Step 2: Smallest frequent UI elements
🗒️ Duties:
- Discover smallest frequent components
- Design for kind components at component-level
- Migrate components
Discover smallest frequent components
In Reply, I appeared for the smallest, reused XMLa and components, with out lots of binding variables, least knowledge pulled from the information layer, and least dependencies wanted (like Glide, for instance):
account_item_layout.xml
compose_recipient_chip.xml
search_suggestion_title.xml
and search_suggestion_item.xml
Design for kind components at component-level
When you’ve flagged the elements, attempt to consider them in numerous display screen sizes. An vital idea right here is the distinction between app, display screen and component-level composables and the place your elements match:
- App-level composable: The only, root composable that occupies all area given to your app, and accommodates all different composables.
- Display-level composable: A composable contained inside the app-level composable that occupies all area given to your app, every usually representing a selected vacation spot when navigating.
- Particular person composables (component-level): All different composables — particular person components, reusable teams of content material, or composables hosted inside screen-level composables.
This step shall be primarily based on particular person composables. On this degree, take into consideration how composables ought to occupy the actual property they’re being given, relatively than being tied to mounted, screen-reliant values. Composables ought to be capable of match properly in any space they’re in. This implies counting on modifiers like fillMaxWidth
, weight
s, and making composables totally reusable and customizable.
That is the place bottom-up migration works greatest — you construct your smallest, adjustable elements first, after which regularly assume bigger. Display-level composables can then rearrange these smaller elements primarily based on the accessible area, display screen sizes, and designs.
On the whole, we advise that your composables observe our API tips. There are some further factors vital for setting the fitting kind components mindset and constructing a reusable, kind issue suitable, composable:
Now let’s migrate some XMLs to Compose!
Migrate components
search_suggestion_item.xml
is a ConstraintLayout
with an ImageView
and two TextView
s:
search_suggestion_item.xml
Straightforward peasy. Whereas ConstraintLayout
exists in Compose, bear in mind you don’t all the time want a 1:1 mapping — you’ll be able to simplify your implementation with Compose. That’s how an XML ConstraintLayout
with constraints for every factor can flip right into a easy combo of Row
s and Column
s in Compose:
Being an excellent Compose scout 🫡, for each new composable, we additionally add a Preview
. Since Reply has a lightweight and darkish theme, we make the most of multipreviews to preview SearchSuggestionItem
in each:
Be aware: In Compose 1.6.0-alpha05 model, PreviewLightDark
multipreview annotation was added, to keep away from the guide creation above.
Now we’re able to hook the primary composable in. In SearchFragment
, we exchange the previous code:
With the brand new one:
A couple of issues to interrupt down right here:
search_suggestion_title.xml
merchandise and its SearchSuggestionHeader
composable observe very comparable steps, so let’s ⏩ that.
compose_recipient_chip.xml
compose_recipient_chip.xml
reveals an attention-grabbing interop functionality.
compose_recipient_chip.xml
The unique XML is a Materials Chip
element which is added to a ChipGroup
in ComposeFragment
:
The ChipGroup
acts as a FlowLayout
container for Chip
s, becoming as many Chip
s as attainable in a single row and may overflow to the following.
This XML is solely changed with a Chip
composable:
So as to add it to the ComposeFragment
, we take full benefit of the interop energy and easily exchange the previous View Chip
with the Compose one, instantly including it to the View ChipGroup
:
Earlier than:
After:
We’re can add a Chip
composable to a View ChipGroup
with out some other modifications. Even the extra advanced logic of expandChip()
, which handles chip’s increasing and collapsing transformation, nonetheless works the identical manner with the Chip
composable. How cool is that?
expandChip()
One other proof of “Interop simply works!” is the account_item_layout.xml
.
account_item_layout.xml
This was used as a RecyclerView
merchandise:
As soon as this factor is migrated to AccountItem
composable, we simply exchange it within the authentic callsite and … it really works!
Be aware: Be sure to are utilizing the most recent variations of
RecyclerView
and Compose to make sure they’re performant collectively. See Utilizing Compose in a RecyclerView to be taught extra.
As a reward, you get to do some enjoyable elimination of previous View code strains, XML recordsdata, styling and theming sources and attributes, customized binding adapter behaviors, and so forth. 😈
💻 PR: Step 2
🏅 MVP participant: Circulate layouts. Keep in mind, Compose migration isn’t all the time a 1:1 mapping to Views. Since ChipGroup
is only a extra opinionated FlowLayout
, you could possibly take into account changing it with Compose Circulate layouts — FlowRow
or FlowColumn
:
Be aware: Compose 1.4.0+ launched Circulate layouts. In earlier variations, consult with Accompanist Circulate layouts as a substitute.
💎 Professional tip: For big parameter lists in previews, use the PreviewParameter
annotation for higher readability.
Phew, let’s pause right here 🎬 ! We’ve coated A LOT on this submit:
- The intro and targets of this migration
- Transient overview of the migration pattern
- First three steps of the captain’s log: 1. migration prep, 2. dependencies & theming, 3. migration of smallest frequent UI
Partially 2️⃣, we proceed our migration journey 🚢 and summarize our takeaways. Keep tuned!
Migrating to Jetpack Compose — an interop love story [part 1]
Migrating to Jetpack Compose — an interop love story [part 2]