Compose 与 View 互操作
问题
如何在 Compose 中使用传统 View?如何在传统 View 中嵌入 Compose?
答案
1. 在 Compose 中使用 View(AndroidView)
当 Compose 尚未提供某个组件(如 MapView、WebView)时,使用 AndroidView:
@Composable
fun WebViewScreen(url: String) {
AndroidView(
factory = { context ->
WebView(context).apply {
settings.javaScriptEnabled = true
webViewClient = WebViewClient()
}
},
update = { webView ->
// state 变化时更新 View
webView.loadUrl(url)
},
modifier = Modifier.fillMaxSize()
)
}
// MapView 示例
@Composable
fun GoogleMap(location: LatLng) {
AndroidView(
factory = { MapView(it).apply { onCreate(null); onResume() } },
update = { mapView ->
mapView.getMapAsync { googleMap ->
googleMap.moveCamera(CameraUpdateFactory.newLatLng(location))
}
}
)
}
2. 在 View 中使用 Compose(ComposeView)
在 Fragment 或 Activity 中嵌入 Compose:
// 在 Fragment 中
class ProfileFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
setContent {
MaterialTheme {
ProfileScreen()
}
}
}
}
}
// 在 XML 布局中
// <androidx.compose.ui.platform.ComposeView
// android:id="@+id/compose_view"
// android:layout_width="match_parent"
// android:layout_height="wrap_content" />
// Activity 中设置内容
binding.composeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent { Greeting("World") }
}
3. 渐进式迁移策略
迁移建议
- 从新功能开始使用 Compose,不必一次性全部迁移
- UI 共享的部分(如自定义 View、第三方 SDK View)可以通过
AndroidView桥接 - 使用
ViewCompositionStrategy正确管理 Compose 的生命周期
常见面试问题
Q1: ViewCompositionStrategy 有哪些策略?
答案:
| 策略 | 说明 | 适用场景 |
|---|---|---|
DisposeOnDetachedFromWindow | View 从 Window 分离时释放(默认) | 普通使用 |
DisposeOnViewTreeLifecycleDestroyed | 宿主 LifecycleOwner destroy 时释放 | Fragment 中使用(推荐) |
DisposeOnLifecycleDestroyed | 指定 Lifecycle destroy 时释放 | 自定义生命周期 |
在 Fragment 中必须使用 DisposeOnViewTreeLifecycleDestroyed,否则 Fragment 进入 back stack 时 Compose 会被意外释放。
Q2: Compose 和 View 混用时主题如何统一?
答案:
使用 MdcTheme(Material Design Components Bridge)或 AppCompatTheme 将 View 系统的主题属性桥接到 Compose:
// build.gradle
// implementation("com.google.accompanist:accompanist-themeadapter-material3:$version")
setContent {
Mdc3Theme {
// Compose 内容会使用 View 系统的 Material 主题
MyComposable()
}
}
或者在 Compose 中直接使用 MaterialTheme,保持两套主题的颜色一致即可。
Q3: AndroidView 的 factory 和 update 有什么区别?
答案:
factory:只在首次 Composition 时调用一次,创建 View 实例。类似onCreateViewupdate:每次相关状态变化导致重组时调用。用于将 Compose 状态同步到 View。类似onBindView
应避免在 update 中创建新的 View 或做耗时操作。