14.8 C
Friday, October 20, 2023

Migrating to Jetpack Compose — an interop love story [part 1] | by Simona Milanović | Android Builders | Sep, 2023

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 would possibly take into account the same method on your Compose migration.

Most of you might be in all probability accustomed to Jetpack Compose and its advantages (simplifies-and-accelerates-UI-Android-development-with-less-code-powerful-tools-and-intuitive-Kotlin 🎶), so we gained’t discuss this. Should 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 can 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 outdated code stays in Views. Relying on capacities, builders refactor outdated code as nicely. However it’s not a should.

That is essential when deciding to begin migrating to Compose. You don’t want a Compose-only app to reap the advantages of Compose. Blended View and Compose code can work collectively and the earlier you introduce Compose, the better your upkeep can 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, try 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 had been:

Testing the “Migration of frequent UI first” technique

Likelihood is you’re working in a staff, in order everyone knows, parallelizing improvement is essential for effectivity and minimizing duplicate work. This migration exhibits that frequent UI elements, shared UI code or, on a bigger scale, design programs may be migrated first, with minimal to no modifications tonon-UI layers. This unblocks parallel migration of complete screens and options.

You’ve gotten 2 doable approaches:

  1. Hold the View elements in parallel to the brand new Compose design system, primarily sustaining two design programs
  2. Migrate completely to a single Compose design system, and whereas doing so, progressively replace current View code to make use of these new elements

For the objectives of this pattern, we selected emigrate all frequent UI and use it in current View code.

Observe: As Compose is an unbundled framework, including it for the primary time has a loading value. For extra data, see the Why must you at all times take a look at Compose efficiency in launch? weblog put up. Use Macrobenchmarks to measure efficiency and make an knowledgeable resolution between the 2 choices above.

Testing interop capabilities

Our take a look at topic is an aged pattern, so it gained’t be getting new options. Subsequently, we opted to migrate current screens to Compose, quite than undertake Compose for brand new screens, as each approaches take a look at the Compose and View interop capabilities. Validating the ability of interop exhibits that refactoring outdated code shouldn’t be a should and that incremental migration to Compose works nicely. You may if you wish to — but it surely’s not a necessity and you’ll depend on interop.

Migrating to Compose whereas holding the unique navigation structure

This migration exhibits that you may hold utilizing Jetpack Navigation or a customized navigation setup, even for screens which are completely Compose, making incremental migration to Compose much less work. Utilizing Navigation Compose isn’t a requisite to make use of Jetpack Compose.

Redesigning a function/display screen? Excellent time emigrate to Compose!

If a significant redesign of a function or a display screen is incoming, this is likely to be an excellent time to board the Compose practice. You’ll have to do some rewriting anyway, so why not take this chance and do it with Compose?

Migrating to Compose? Excellent time so as to add kind issue assist!

This migration exhibits how easy it’s to introduce assist for kind components when you begin utilizing composable components and screens, and it supplies ideas and steerage on adopting the correct kind components mindset from begin.

Views to Compose don’t at all times want a 1:1 mapping

Should you’ve used one part in Views, you won’t want the identical part in Compose. Reap the benefits of migration to rethink the implementation of your components — change them or simplify them, if wanted. This pattern exhibits examples of how one can swap from, for instance, View ConstraintLayouts to Compose Rows and Columns as a substitute.

Reply is an aged pattern. It’s a easy e mail app, with primary performance of displaying emails, filtering, organizing, and navigating between screens. It consists of Search, Residence, E-mail and Compose (composing an e mail) screens.

Observe: 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 remaining. So that you would possibly discover it doesn’t have a ViewModel, however quite a simulation of enterprise logic within the EmailStore. It additionally doesn’t have any assessments 😬. This makes it fairly totally different from a manufacturing app (hopefully!). However as samples are oversimplified by design, this should do.

Observe: Reply makes use of M2. Relatively than migrating to Compose and M3 on the similar time, we selected to separate it into two duties to promote an incremental and secure migration course of. Reply M3 migration is deliberate for a V2 sequel, together with navigation and animation. Nonetheless, we encourage you to pair Compose with M3 to unlock its full potential.

This log follows the steps we took when migrating Reply. Nonetheless, everybody’s free to decide on their very own path! Use this as a information, quite 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 complicated elements [in part 2]
Step 4: Migration of low threat screens [in part 2]
Step 5: Migration of extra complicated screens [in part 2]

Step 0: Migration prep

🗒️ Duties:

  • Learn migration documentation
  • Analyze and take a look at 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 essential to do your preparation nicely, earlier than really beginning. Migrating from Views to Compose could be a mammoth job — it takes time, and you need to prioritize security and incrementation over pace. Presuming you might have primary 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 non-obligatory, nice-to-haves:

  • Is the app following the finest structure practices? ✅
  • How good is your staff’s data of primary Compose? ✅ 😎
  • Do you might have the time and assets 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 courses in ui/frequent, so we used slightly creativeness and migrated some further ones — elements outfitted to be included in one other XML structure or reused by way of its binding. Play fake for the sake of the tip purpose 🙂.

Now that we now have studied, analyzed, and provide you with a plan, it’s time to begin coding.

Each migration step has an MVP participant and a professional tip.

🏅 MVP participant: Screenshot testing. A vital factor to facilitate, as migration from Views to Compose may deliver some difficult-to-catch UI regression. To study 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 function, display screen, or large chunk of elements. And if all this rewrite work is being accomplished, why not get the extra advantage of 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 information you want.

Theming would typically be the second code change. Since organising theming is primary Compose data, we initially determined to make use of the mdctheme adapter to rapidly maps the XML theming to a corresponding Compose one. Nonetheless, the adapter has since been deprecated and our steerage now recommends organising the M2 theming manually, following the Compose M2 theming codelab.

Observe: Materials 3 is our really helpful design system. See Migrate XML themes to Compose and the best way to use the Materials 3 Theme Builder for extra data.

💻 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 instrument helps you visualize Materials dynamic shade, simply create a customized M3 theme, and export it to code.

💎 Professional tip: A secure and incremental Compose migration follows this order:

  1. Smallest frequent elements first
  2. Scale to extra complicated frequent elements
  3. Low-risk, low-complexity screens and options
  4. 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 regarded for the smallest, reused XMLa and components, with out a whole lot of binding variables, least knowledge pulled from the info layer, and least dependencies wanted (like Glide, for instance):

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 several display screen sizes. An essential 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 house given to your app, and comprises all different composables.
  • Display-level composable: A composable contained throughout the app-level composable that occupies all house given to your app, every typically 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 can be based mostly on particular person composables. On this degree, take into consideration how composables ought to occupy the actual property they’re being given, quite than being tied to mounted, screen-reliant values. Composables ought to have the ability to match nicely in any space they’re in. This implies counting on modifiers like fillMaxWidth, weights, and making composables totally reusable and customizable.

That is the place bottom-up migration works finest — you construct your smallest, adjustable elements first, after which progressively assume bigger. Display-level composables can then rearrange these smaller elements based mostly on the accessible house, display screen sizes, and designs.

Basically, we advise that your composables observe our API pointers. There are some further factors essential for setting the correct kind components mindset and constructing a reusable, kind issue appropriate, composable:

Now let’s migrate some XMLs to Compose!

Migrate components

search_suggestion_item.xml is a ConstraintLayout with an ImageView and two TextViews:


Straightforward peasy. Whereas ConstraintLayout exists in Compose, bear in mind you don’t at all times want a 1:1 mapping — you may simplify your implementation with Compose. That’s how an XML ConstraintLayout with constraints for every ingredient can flip right into a easy combo of Rows and Columns 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 reap the benefits of multipreviews to preview SearchSuggestionItem in each:

Observe: In Compose 1.6.0-alpha05 model, PreviewLightDark multipreview annotation was added, to keep away from the handbook creation above.

Now we’re able to hook the primary composable in. In SearchFragment, we exchange the outdated 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 exhibits an fascinating interop functionality.


The unique XML is a Materials Chip part which is added to a ChipGroup in ComposeFragment:


The ChipGroup acts as a FlowLayout container for Chips, becoming as many Chips as doable in a single row and might overflow to the subsequent.

This XML is just 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 outdated View Chip with the Compose one, straight including it to the View ChipGroup:

Earlier than:


We’re can add a Chip composable to a View ChipGroup with out another modifications. Even the extra complicated logic of expandChip(), which handles chip’s increasing and collapsing transformation, nonetheless works the identical method with the Chip composable. How cool is that?


One other proof of “Interop simply works!” is the account_item_layout.xml.


This was used as a RecyclerView merchandise:

As soon as this ingredient is migrated to AccountItem composable, we simply exchange it within the authentic callsite and … it really works!

Observe: Be sure to are utilizing the newest variations of RecyclerView and Compose to make sure they’re performant collectively. See Utilizing Compose in a RecyclerView to study extra.

As a reward, you get to do some enjoyable removing of outdated View code strains, XML recordsdata, styling and theming assets and attributes, customized binding adapter behaviors, and so forth. 😈

💻 PR: Step 2

🏅 MVP participant: Movement layouts. Bear in mind, Compose migration isn’t at all times a 1:1 mapping to Views. Since ChipGroup is only a extra opinionated FlowLayout, you may take into account changing it with Compose Movement layoutsFlowRow or FlowColumn:

Observe: Compose 1.4.0+ launched Movement layouts. In earlier variations, discuss with Accompanist Movement 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 lined A LOT on this put up:

  • The intro and objectives 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

Partly 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]

Latest news
Related news


Please enter your comment!
Please enter your name here