Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Strategies for Migrating to Jetpack Compose
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Mohit S
April 19, 2022
Programming
660
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Strategies for Migrating to Jetpack Compose
Mohit S
April 19, 2022
More Decks by Mohit S
See All by Mohit S
Guide to Improving Compose Performance
heyitsmohit
0
330
Building Shared UIs across Platforms with Compose
heyitsmohit
1
710
Building Multiplatform Apps with Compose
heyitsmohit
2
620
Building StateFlows with Jetpack Compose
heyitsmohit
6
2k
Building Android Testing Infrastructure
heyitsmohit
1
640
Migrating to Kotlin State & Shared Flows
heyitsmohit
1
880
Using Square Workflow for Android & iOS
heyitsmohit
1
520
Building Android Infrastructure Teams at Scale
heyitsmohit
3
420
Challenges of Building Kotlin Multiplatform Libraries
heyitsmohit
1
520
Other Decks in Programming
See All in Programming
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
120
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
7.9k
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
360
AI駆動開発を妨げる技術的負債の解消アプローチ / ai-refactoring-approach
minodriven
12
6.5k
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
280
鹿野さんに聞く!『TypeScriptコードレシピ集』で磨く実践力
tonkotsuboy_com
2
750
Inside Stream API
skrb
1
770
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
6.5k
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
800
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
7k
Featured
See All Featured
So, you think you're a good person
axbom
PRO
2
2.1k
Mind Mapping
helmedeiros
PRO
1
260
Building an army of robots
kneath
306
46k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
450
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
RailsConf 2023
tenderlove
30
1.5k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
310
How to Think Like a Performance Engineer
csswizardry
28
2.7k
AI: The stuff that nobody shows you
jnunemaker
PRO
8
730
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
240
Transcript
Mohit Sarveiya Strategies for Migrating to Jetpack Compose @heyitsmohit
Strategies for Migrating to Jetpack Compose • Challenges • How
to think about migration • Strategies & Tools
Challenges
Code size Code size Time
Greenfield Project • Easier to use Compose • Fewer roadblocks
to use Compose
Code size Code size Time
Roadmap 0% Compose 100% Compose
Roadmap 0% Compose 100% Compose Roadblock Roadblock
Roadmap • Long road • Obstacles along the way
Arch Fragmentation Codebase
Arch Fragmentation Codebase Legacy code
Arch Fragmentation Codebase Legacy code Feature A Feature B
Challenges • Interoperability
Interop • Compose to old view system
Interop Codebase Feature A Compose View Legacy code
Interop Codebase Legacy code Feature A Compose View
Interop • Compose to old view system • Use old
views in Compose
Interop Codebase Legacy code Feature A Custom View
Interop Codebase Feature A Compose with Custom View Legacy
code
Challenges • Interoperability • Architecture
Architecture Codebase Legacy code
Arch Challenges • Not using composition over inheritance
Legacy Code Base Fragment Too much logic
Legacy Code Base Fragment Too much logic Fragment Fragment Fragment
…
Legacy Code Base Fragment Fragment Fragment Fragment … Refactor to
Compose
Legacy Code Base View Holders Too much logic
Legacy Code Base View Holders Too much logic View Holder
View Holder View Holder … Refactor to Compose
Arch Challenges • Not using composition over inheritance • Navigation
App Architecture API Domain Navigation UI
Navigation NavHost(navController, startDestination = "profile") { composable("profile") { Profile( /*...*/
) } composable("friendslist") { FriendsList( /*...*/ ) } }
Legacy Navigation Main Activity Activity Activity
Navigation Main Activity Fragment A Fragment B Fragment C ...
Challenges • Interoperability • Architecture • Testing
Testing Codebase 1% Code coverage 5% Code coverage
Challenges • Interoperability • Architecture • Testing • Tooling
Compose Upgrades Version Time alpha05 alpha06
Challenges • Interoperability • Architecture • Testing • Tooling
Collaboration Org CI Arch Design Team Feature Teams Teams
Strategies
Roadmap 0% Compose 100% Compose
Roadmap 0% Compose 100% Compose Milestone Milestone
Proposal • Specify milestones over time • Assess & Mitigate
Risks • Documentation
Roadmap 0% Compose 100% Compose Milestone
Complexity Codebase High Low Medium
Migration Phase 1 Complexity Migration time Low
Migration Phase 2 Complexity Migration time Medium
Migration Phase 1 • Migrate Design Components
Example Feature A Feature B Feature C Common Design
Components
Example Common Design Components App A App B App
C
Collaboration Org CI Arch Design Team Feature Teams Teams
Migration Phase 1 • Migrate design components to Compose
Interoperability
Interop 9:41
Interop 9:41 Convert to compose
Interop <ConstraintLayout> <ImageView /> <Button /> <TextView /> <TextView />
</ FrameLayout> 9:41
Interop <ConstraintLayout> <ImageView /> <Button /> <TextView /> <TextView />
</ FrameLayout> 9:41
Interop <ConstraintLayout> <ImageView /> <Button /> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="wrap_content"
/> </ FrameLayout>
Compose View binding.composeView.apply { setContent { } }
Compose View binding.composeView.apply { setContent { MaterialTheme { DescriptionView() }
} }
Challenges strings.xml dimen.xml theme.xml Compose Resuse
Compose View @Composable fun DescriptionView() { Text( text = stringResource(id
= R.string.title) ) }
Compose View @Composable fun DescriptionView() { Text( modifier = Modifier.padding(dimensionResource(R.id.margin_small))
) }
Challenges • How do you reuse dimen and string resources?
• Interop Theming
Challenges strings.xml dimen.xml theme.xml Compose Resuse
Interop Theming implementation “com.google.android.material:compose-theme-adapter:1.1.1”
Interop Theming binding.composeView.apply { setContent { MaterialTheme { DescriptionView() }
} }
Interop Theming binding.composeView.apply { setContent { MdcTheme { DescriptionView() }
} }
Challenges • How do you reuse dimen and string resources?
• Interop Theming • View lifecycle
Compose View binding.composeView.apply { setContent { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) }
}
Phase 1 Migration Common Design Components App A App
B App C
Common Design Components • View all compose components • Document
design system
airbnb/Showkase Code ! Issues Pull Requests Showkase Compatible with Compose
1.0.4 Showcase 1.0.0-beta12 Showkase is an annotation-processor based Android library that helps you organize, discover, search and visualize Jetpack Compose UI elements.
Showkase 9:41 App com.app General Logs Other Keyline overlay Slow
down animations Network Activity Logs Lifecycle logs Show UX
Showkase 9:41 App com.app General Logs Other Keyline overlay Slow
down animations Network Activity Logs Lifecycle logs Show UX 9:41 Design Components Components Colors Typography
Showkase Compose Design Spec Generate
Showkase @ShowkaseRoot class AppRootModule: ShowkaseRootModule
Showkase startActivity(Showkase.getBrowserIntent(this))
Showkase @Preview(name = “Custom component", group = "Custom group") @Composable
fun PostView()
Showkase 9:41 Design Components Post view Title
Arch Fragmentation Codebase Legacy code 100% Compose 100% Compose
Interop @Composable fun PostView() { AndroidView(factory = { context ->
})
Interop @Composable fun PostView() { AndroidView(factory = { context ->
CustomView(context).apply { layoutParams = LinearLayout.LayoutParams( MATCH_PARENT, WRAP_CONTENT ) } })
Interop • ComposeView • AndroidView
Migration Phase 1 • Migrate Design Components
Roadmap 0% Compose 100% Compose Milestone
Roadmap 0% Compose 100% Compose Milestone Milestone
Migration Phase 2 Complexity Migration time Medium
Testing Codebase 1% Code coverage 5% Code coverage
Migration Phase 2 • Migrate medium complexity features • Setup
scaffolding to catch regressions
Testing
Testing Infra Compose Conversions Testing Infra
Goals • Catch regressions earlier • Increase covers with compose
migration
Testing Infra • Snapshot testing • UI Testing Interop
cashapp/paparazzi Code ! Issues Pull Requests Paparazzi An Android library
to render your application screens without a physical device or emulator.
Paparazzi Screenshot Unit Test
Paparazzi • 1.0.0-Snapshot has compose support
Paparazzi @get:Rule val paparazzi = Paparazzi()
Paparazzi @get:Rule val paparazzi = Paparazzi() @Test fun testView() {
paparazzi.snapshot { PostView(uiState) } }
Paparazzi 9:41 Post Title
Paparazzi Git (LFS) Snapshot
Testing Infra • Snapshot testing • UI Testing Interop
Interop <ConstraintLayout> <ImageView /> <Button /> <ComposeView /> </ FrameLayout>
9:41
Interop 9:41 Semantics Tree
Compose UI Testing @get:Rule val composeTestRule = createAndroidComposeRule<MainActivity>()
Compose UI Testing @Test fun postViewTest() { composeTestRule.onNodeWithText(“Title").assertIsDisplayed() }
Interop @Composable fun PostView() { AndroidView(factory = { context ->
CustomView(context) }) }
Interop @Test fun postViewTest() { composeTestRule.onNodeWithText("Submit").performClick() }
Interop @Test fun postViewTest() { composeTestRule.onNodeWithText(“Submit").performClick() Espresso.onView(withText(“Success")).check(matches(isDisplayed())) }
Migration Phase 2 • Migrate medium complexity features • Setup
scaffolding to catch regressions
Migration Phases 0% Compose Milestones
Migration Phases • Milestones depend on complexity & code size
• Low Complexity -> High Complexity
Migration Phases 0% Compose Milestones Testing Infra
Internationalization
Migration Phases 0% Compose Milestones
Languages Support strings.xml values-en values-de values-fr strings.xml strings.xml
Languages Support Add strings
Languages Support Translation service Add strings
Languages Support Translation service Provides translated strings Add strings
Languages Support • Compose language interop
adrielcafe/lyricist Code ! Issues Pull Requests Lyricist The missing I18N
and L10N multiplatform library for Jetpack Compose!
Languages Support Strings (xml) Types KSP Composition Local
Languages Support strings.xml values values-pt strings.xml
Languages Support <resources> <string name=“greeting”>Hello world </ string> <string-array name="array">
<item>Avocado </ item> </ string-array> <plurals name="plurals"> <item quantity="zero">%d zero </ item> </ plurals> </ resources>
Languages Support <resources> <string name=“greeting”>Olá mundo </ string> <string-array name="array">
<item>Abacate </ item> </ string-array> <plurals name="plurals"> <item quantity="zero">%d zero </ item> </ plurals> </ resources>
Languages Support ksp { arg("lyricist.xml.resourcesPath", android.sourceSets.main.res.srcDirs.first().absolutePath) arg("lyricist.xml.moduleName", “xml") arg("lyricist.xml.defaultLanguageTag",
"en") }
Languages Support data class Strings( val greeting: String, val array:
List<String>, val plurals: (quantity: Int) -> String ) object Locales { val En = "en" val Pt = "pt" }
Languages Support @Composable public fun <T> ProvideStrings() { CompositionLocalProvider( provider
provides lyricist.strings ) }
Languages Support @Preview @Composable fun PostViewPreview() { val xmlStrings =
rememberXmlStrings() ProvideXmlStrings(xmlStrings) { Text(text = xmlStrings.greeting) } }
Languages Support @Preview @Composable fun PostViewPreview() { val xmlStrings =
rememberXmlStrings() ProvideXmlStrings(xmlStrings) { Text(text = xmlStrings.greeting) } }
Languages Support @Preview @Composable fun PostViewPreview() { val xmlStrings =
rememberXmlStrings() ProvideXmlStrings(xmlStrings) { Text(text = xmlStrings.greeting) } }
Languages Support @Preview @Composable fun PostViewPreview() 9:41 Post Hello World
Languages Support @Preview(locale = “pt”) @Composable fun PostViewPreview() 9:41 Post
Olá mundo
Migration Phases 0% Compose Milestones
Tooling
Kotlin Upgrades This version (1.1.1) of the Compose Compiler requires
Kotlin version 1.6.10 but you appear to be using Kotlin version 1.6.20 which is not known to be compatible.
Kotlin Upgrades composeOptions { kotlinCompilerExtensionVersion compose_version suppressKotlinVersionCompatibilityCheck true
} Not Recommended
Kotlin Upgrades • Wait for compose to be updated
None
Kotlin Upgrades • Wait for compose to be updated •
Test out compose upgrades
None
Kotlin Upgrades • Wait for compose to be updated •
Test out compose upgrades
Strategies for Migrating to Jetpack Compose • Challenges • How
to think about migration • Strategies & Tools
Thank You! www.codingwithmohit.com @heyitsmohit