组件化路由与模块通信
组件化不是把包拆成很多 module,而是让业务边界、依赖方向和发布协作更清晰。中高级面试常追问路由、通信和依赖治理。
一、组件化解决什么问题
| 问题 | 组件化目标 |
|---|---|
| 业务耦合 | feature 边界清晰 |
| 编译慢 | 模块增量构建 |
| 多团队协作 | 独立开发/测试 |
| 依赖混乱 | 依赖方向可控 |
二、模块拆分方式
- app 壳工程:组装入口。
- feature module:业务功能。
- core/common:基础能力。
- api/contract:跨模块接口。
依赖方向应从上层依赖抽象,避免 feature 之间直接互相依赖。
三、路由框架原理(以 ARouter 类框架理解)
核心流程:编译期扫描注解 → APT/KSP 生成路由表 → 运行时按 path 查找目标 → 拦截器处理登录/权限/降级 → 跳转或返回服务实例。
interface UserService {
fun currentUserId(): String?
}
跨模块不要直接调用实现类,而是依赖 UserService 这样的 contract。
四、模块通信方式
| 方式 | 适用 | 风险 |
|---|---|---|
| 路由跳转 | 页面级跳转 | path 字符串错误 |
| 接口下沉 | 同步能力调用 | contract 膨胀 |
| 事件总线 | 广播式通知 | 难追踪、生命周期问题 |
| Result API | 页面结果回传 | 复杂链路难维护 |
五、路由拦截、降级与灰度
登录校验、权限校验、A/B 实验、页面不存在降级都适合放在拦截器链里。路由失败必须有兜底,不能直接 crash。
六、和 Gradle 工程化的关系
组件化设计关注业务边界;Gradle 工程化关注构建配置、依赖版本、产物和性能。两者相关但不是一回事。
高频面试题
Q1:组件化和模块化区别? 答:模块化偏代码物理拆分,组件化更强调业务组件独立开发、独立测试、按契约通信和可组装。
Q2:ARouter 这类框架大概怎么实现? 答:编译期注解处理生成路由表,运行时初始化加载,按 path 找目标 class/provider,再通过拦截器处理统一逻辑。
Q3:跨模块通信为什么不直接依赖实现? 答:直接依赖会导致 feature 耦合、编译依赖变重、循环依赖风险;接口下沉能保持依赖方向稳定。
易错点 / 追问
- 不要为了组件化制造过多小 module。
- 不要把所有通信都塞进 EventBus。
- 路由 path 要集中治理,否则重构时容易断链。