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
Mohit S
April 19, 2022
Programming
2
490
Strategies for Migrating to Jetpack Compose
Mohit S
April 19, 2022
Tweet
Share
More Decks by Mohit S
See All by Mohit S
Guide to Improving Compose Performance
heyitsmohit
0
130
Building Shared UIs across Platforms with Compose
heyitsmohit
1
530
Building Multiplatform Apps with Compose
heyitsmohit
2
400
Building StateFlows with Jetpack Compose
heyitsmohit
6
1.7k
Building Android Testing Infrastructure
heyitsmohit
1
370
Migrating to Kotlin State & Shared Flows
heyitsmohit
1
660
Using Square Workflow for Android & iOS
heyitsmohit
1
360
Building Android Infrastructure Teams at Scale
heyitsmohit
3
270
Challenges of Building Kotlin Multiplatform Libraries
heyitsmohit
1
380
Other Decks in Programming
See All in Programming
LLM生成文章の精度評価自動化とプロンプトチューニングの効率化について
layerx
PRO
2
130
Realtime API 入門
riofujimon
0
110
CSC305 Lecture 13
javiergs
PRO
0
130
『ドメイン駆動設計をはじめよう』のモデリングアプローチ
masuda220
PRO
7
430
JaSST 24 九州:ワークショップ(は除く)実践!マインドマップを活用したソフトウェアテスト+活用事例
satohiroyuki
0
260
Streams APIとTCPフロー制御 / Web Streams API and TCP flow control
tasshi
1
290
go.mod、DockerfileやCI設定に分散しがちなGoのバージョンをまとめて管理する / Go Connect #3
arthur1
10
2.4k
Universal Linksの実装方法と陥りがちな罠
kaitokudou
1
220
CSC509 Lecture 09
javiergs
PRO
0
100
デプロイを任されたので、教わった通りにデプロイしたら障害になった件 ~俺のやらかしを越えてゆけ~
techouse
52
32k
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism- An Example
philipschwarz
PRO
0
170
Progressive Web Apps für Desktop und Mobile mit Angular (Hands-on)
christianliebel
PRO
0
110
Featured
See All Featured
A designer walks into a library…
pauljervisheath
202
24k
Music & Morning Musume
bryan
46
6.1k
Teambox: Starting and Learning
jrom
132
8.7k
How GitHub (no longer) Works
holman
311
140k
Testing 201, or: Great Expectations
jmmastey
38
7k
It's Worth the Effort
3n
183
27k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
A Philosophy of Restraint
colly
203
16k
BBQ
matthewcrist
85
9.3k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
3
370
Documentation Writing (for coders)
carmenintech
65
4.4k
Building Adaptive Systems
keathley
38
2.2k
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