Compose ↔ View interop & migration
Both worlds coexist in one app — migration is incremental:
- Compose inside Views: drop a
ComposeViewinto the layout and fill it viasetContent { }. In fragments you must setViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed— otherwise the composition outlives the fragment's view and leaks. - Views inside Compose:
AndroidView(factory = { context -> MapView(context) }, update = { view -> ... })— for components with no Compose equivalent (maps, WebView, ad SDKs, custom charts). - Theme bridging: adapter approaches keep Material themes in sync across XML ↔ Compose; keeping design tokens in one source matters.
Migration strategy (official guidance): bottom-up — small components/new screens in Compose first, then whole screens, navigation last. New features are written in Compose; old screens migrate as they are touched.
// 1) Fragment-də ComposeView (View → Compose)
override fun onCreateView(...): View =
ComposeView(requireContext()).apply {
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
setContent {
BankTheme {
TransferScreen()
}
}
}
// 2) Compose-da köhnə custom view (Compose → View)
@Composable
fun SignatureBox(onSigned: (Bitmap) -> Unit) {
AndroidView(
factory = { context ->
SignatureView(context).apply { listener = onSigned }
},
update = { view -> view.clearIfNeeded() }
)
}Interop in both directions
The expected shape of the migration answer: (1) no big bang — incremental; (2) where to start — design-system components (buttons, inputs) and new screens; (3) the risky spots — ComposeView inside RecyclerView items (performance), composition strategies in fragments, keeping two theme systems in sync; (4) the team side — code review + pairing for those new to Compose. Your situation (XML fluent, learning Compose) is an asset here: "my learning path mirrors the migration path".
🛠 Practice task
Wire up interop in both directions:
- Add a
ComposeViewto a fragment. Run it without aViewCompositionStrategyfirst and check LeakCanary; then setDisposeOnViewTreeLifecycleDestroyed. - Show a legacy View inside a Compose screen via
AndroidView(e.g. aWebViewor a simple custom view) and log when theupdatelambda runs.
Done when: you have a phased plan ready for "how would you migrate a large XML codebase".
📚 Sources and documentation
- Interoperability APIsofficialdeveloper.android.com
- Migration strategyofficialdeveloper.android.com