The Android community adopts Jetpack Compose more and more each day. But what about our existing apps? Adopting existing apps to Jetpack Compose might be an overwhelming task when the migration is not planned well.
In this talk, we will see the Compose migration strategy used in DNB. We will briefly talk about the interoperability APIs and how they are used in this migration process. We will also talk about how we are adopting our internal design system to Jetpack Compose. Finally, we will discuss the challenges we faced during this migration.
15. Top-down
return ComposeView(requireContext()).apply {
// Dispose the Composition when viewLifecycleOwner is destroyed
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)
)
setContent {
// Compose World
}
}
TopDownFragment.kt
16. Top-down
return ComposeView(requireContext()).apply {
// Dispose the Composition when viewLifecycleOwner is destroyed
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)
)
setContent {
// Compose World
// Vertical Linear Layout
Column {
// Add views as AndroidView by creating
// programatically or inflating from XML
}
}
}
TopDownFragment.kt
18. Top-down
setContent {
// Vertical Linear Layout
Column {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
// Inflate it from XML
inflater.inflate(
R.layout.fancy_content,
container,
false
)
},
update = { view ->
// View's been inflated or state read in
// this block has been updated
}
)
}
} TopDownFragment.kt
19. Top-down
setContent {
// Vertical Linear Layout
Column {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
// Create view programatically
// android.widget.Button
Button(requireContext())
},
update = { view ->
// View's been inflated or state read in
// this block has been updated
}
)
}
}
TopDownFragment.kt
20. Top-down
setContent {
// Vertical Linear Layout
Column {
Button(onClick = {}) {
Text("I am a compose button”)
}
}
}
TopDownFragment.kt
26. Bottom-up
buttonComposeView.apply {
// Dispose the Composition when viewLifecycleOwner is destroyed
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)
)
}
BottomUpFragment.kt
27. Bottom-up
buttonComposeView.apply {
// Dispose the Composition when viewLifecycleOwner is destroyed
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)
)
setContent {
// In Compose world
}
}
BottomUpFragment.kt
28. Bottom-up
buttonComposeView.apply {
// Dispose the Composition when viewLifecycleOwner is destroyed
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)
)
setContent {
// In Compose world
Button(onClick = {}) {
Text(text = "I am migrated Button")
}
}
}
BottomUpFragment.kt
38. Migration Plan
• Start with Eufemia & Tetris
• Eufemia
• Migrate design system to Compose (colours, shapes, typography)
• Convert each component to Compose one by one
• Tetris
• Create Components as composables from the scratch
• Use AndroidView for Eufemia Android Views
39. Migration Plan
• Pick a screen in the app
• Apply bottom-up approach
• Create components in Tetris & Eufemia
• Iterate for all screens
48. Migration Plan
• Only change the way views are
presented (ComposeView +
Composables)
• No change in navigation
• After all screens are migrated,
remove fragments