Jetpack Compose 是否已完全取代 XML 布局?迁移的最佳实践是什么?
解读
面试官想确认三件事:
- 你对国内真实存量代码与增量代码比例有体感——大厂 70% 以上页面仍是 XML,Compose 仅在新模块/新 App 落地;
- 你知道官方“可共存”路线,而非“一刀切”;
- 你能给出一条可落地、可灰度、可回退的迁移路径,并解决团队最关心的编译耗时、包体积、人员学习成本、自动化测试回归四大痛点。
答成“完全取代”或“XML 已死”会被判为脱离实际;答成“慢慢迁移”却不给策略,会被判为套话。
知识点
- 官方共存方案:View ↔ Compose 双向互调(ComposeView、AndroidView、ViewCompositionStrategy);
- 国内存量包袱:自定义 ViewGroup、DataBinding、插件化换肤、热修复、厂商魔改 ROM 对 Compose 的兼容坑;
- 构建指标:Compose 编译器插件增量 kapt 耗时、Composer 方法数、运行时库 1.3 M 起步、R8/ProGuard 规则收紧;
- 灰度策略:新功能 Compose 优先、老页面 ROI 评估(复用度、迭代频率、崩溃率)、Feature Flag + 路由层(ARouter/FragmentNavigator)动态降级;
- 测试回归:Espresso 与 ComposeTestRule 混用、Maestro/Apium 脚本改造、Compose 语义树与 View 树并存时截图比对方案;
- 人员培训:双周“Compose CodeLab”、强制 Code Review 红线(禁止 remember 无 key、禁止滥用 DisposableEffect)、Lint 自定义规则扫描;
- 性能底线:重组计数监控(CompositionLocal + Metric)、帧率掉帧回退到 View、启动耗时与包体积 Gate 在 CI 中强制卡点。
答案
“Compose 在国内尚未完全取代 XML,官方路线是‘可长期共存、逐步迁移’。
迁移分四步:
① 基建层:升级 AGP 8.0 + Kotlin 1.9,R8 开启 Compose 专用优化,CI 新增 Compose 编译耗时阈值;
② 模块边界:用 Compose 写新 Fragment,老 Activity 通过 ComposeView 局部试点,保留原有 DataBinding 模块不动;
③ 灰度回退:在路由层加开关,Compose 页面异常率>0.3% 或掉帧>1% 自动降级到 XML 实现;
④ 人员与规范:建立 Compose 组件库(主题、列表、弹窗)并写死 Design Token,Code Review 强制检查 rememberSaveable、derivedStateOf 使用场景,两周一次性能复盘。
按此节奏,我们团队 6 个月内把 30% 高频迭代模块迁到 Compose,包体积增加 0.8 M,编译耗时增加 12%,但 UI 代码量减少 38%,线上崩溃率持平,符合预期。”
拓展思考
- 折叠屏与多尺寸屏幕下,Compose 的 WindowSizeClass 与 XML 的 resource 限定符如何统一设计 token?
- 国内厂商主题换肤(如 MIUI 动态图标色)需要反射修改 Compose 的 ColorScheme,如何做才能通过 Google Play 政策?
- Compose Compiler 2.0 宣称支持“编译期重组消除”,在大型模块化工程(500+ 子模块)中,kapt 与 KSP 混用会不会重新触发 Annotation Processor 的全量编译?如何验证?