跳到主要内容

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 有哪些策略?

答案

策略说明适用场景
DisposeOnDetachedFromWindowView 从 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: AndroidViewfactoryupdate 有什么区别?

答案

  • factory:只在首次 Composition 时调用一次,创建 View 实例。类似 onCreateView
  • update:每次相关状态变化导致重组时调用。用于将 Compose 状态同步到 View。类似 onBindView

应避免在 update 中创建新的 View 或做耗时操作。

相关链接