Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Strategies for Migrating to Jetpack Compose
Search
Mohit S
April 19, 2022
Programming
700
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
360
Building Shared UIs across Platforms with Compose
heyitsmohit
1
750
Building Multiplatform Apps with Compose
heyitsmohit
2
660
Building StateFlows with Jetpack Compose
heyitsmohit
6
2.1k
Building Android Testing Infrastructure
heyitsmohit
1
670
Migrating to Kotlin State & Shared Flows
heyitsmohit
1
920
Using Square Workflow for Android & iOS
heyitsmohit
1
560
Building Android Infrastructure Teams at Scale
heyitsmohit
3
450
Challenges of Building Kotlin Multiplatform Libraries
heyitsmohit
1
550
Other Decks in Programming
See All in Programming
ChromeでローカルLLM
ryu1013
0
160
SalesForceを内製化!? ~ HR事業を支える顧客管理基盤のインフラを大公開 ~
oku053
0
190
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
130
PyConTW 2026 - AI Coding 不只是工具升級, 區域醫院醫療資訊系統協作開發與資訊團隊轉型實踐
cclai999
0
110
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
270
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
170
Web Framework Benchmark Battle 2026, Any%
a_matsuda
2
2.7k
Railsバージョンを4倍にした話
optim
0
500
Rでドレミ/Do-Re-Mi_with_R
florets1
0
130
AIに “答え“を書かせるのを やめてみた
___akari11
0
120
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.8k
Lambda durable functionsでHuman in the Loopを楽に…楽に……
har1101
0
150
Featured
See All Featured
Game over? The fight for quality and originality in the time of robots
wayneb77
1
310
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
Leo the Paperboy
mayatellez
10
2.4k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.6k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
270
Prompt Engineering for Job Search
mfonobong
0
520
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
Agile that works and the tools we love
rasmusluckow
331
22k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
540
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