Compose 与传统 View 互操作策略:分层解耦实战
互操作多模块架构治理
大多数企业级应用都会经历较长的迁移窗口期,Compose 不可能一蹴而就。在并存阶段,我们需要构建清晰的互操作边界,确保宿主模块的生命周期、主题体系与性能指标不被破坏。
我们建议从“阅读型模块”切入,引入 `ComposeView` 作为桥接容器,并通过统一的 Design System Adapter 将颜色、排版、间距等设计令牌映射到 Compose `MaterialTheme`。
模块化拆分原则
- 桥接层独立成模块:`ui-interop` 仅负责 View 与 Compose 的交互,避免业务模块直接依赖实现细节;
- Compose 入口保持无状态:通过参数传递数据与回调,将状态托管在 ViewModel 或 UseCase 层;
- 对外暴露稳定接口:使用 `@Stable` 数据结构作为边界契约,降低重组带来的 diff 噪音。
Note: 互操作模块需单独配置 R8 keep 规则,保留 `androidx.compose` 相关类,防止代码压缩阶段误删。
桥接层实现要点
如下示例展示了如何在 View 模块中安全托管 Compose,并同步宿主主题与生命周期。我们推荐使用 `ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed` 避免内存泄漏。
class ComposeInterstitial @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {
private val composeView = ComposeView(context).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
}
init {
addView(composeView)
}
fun render(state: InteropState, onAction: (InteropAction) -> Unit) {
composeView.setContent {
LegacyThemeAdapter {
InteropScreen(state = state, onAction = onAction)
}
}
}
}
@Stable
data class InteropState(
val title: String,
val illustrations: ImmutableList<Illustration>
)监控与性能回归
互操作阶段的性能监控尤为关键。我们在 FrameMetricsAggregator 中记录新旧界面的首帧时间,并借助 `Choreographer.FrameCallback` 捕获掉帧,将指标写入 Grafana。
当 Compose 模块占比超过 60% 时,可考虑将 `ComposeView` 迁移为完全的 `Activity`/`Fragment` 层级,以减少额外的测量与布局成本。