项目越大,构建越慢,耦合越重。模块化的目的不是炫技,是为了让团队能并行开发、独立测试、快速构建。
一、模块化的三种粒度
常见分层:
app:Application、导航、依赖注入feature:xxx:具体业务功能core:common:公共工具、扩展core:network:网络层core:datastore:数据存储
二、Feature Module 的依赖方向
// feature:home 的 build.gradle.kts
dependencies {
implementation(project(":core:common"))
implementation(project(":core:network"))
implementation(project(":feature:detail")) // 直接依赖其他 feature,不推荐
}
更好的做法是反向依赖:
Feature 只依赖 core 模块
模块间通信通过路由或事件总线
app模块负责把 feature 拼起来
// 用接口解耦
interface HomeNavigator {
fun openDetail(itemId: String)
}
三、Dynamic Feature Module
// build.gradle.kts of feature:video
dynamicFeature = true
// app 模块的 build.gradle.kts
android {
dynamicFeatures += setOf(":feature:video", ":feature:ar")
}
动态模块按需下载,适合:
大体积资源,如 AR、视频特效
不常用功能,如高级设置、企业版功能
地区/语言包
四、App Bundle 与 Dynamic Delivery
上传 Google Play 时用 AAB 格式,Play 会根据设备 ABI、语言、屏幕密度动态分发 APK。
./gradlew bundleRelease
结合 Dynamic Feature,用户第一次安装只下载基础包,后续按需下载功能模块。
五、模块化常见坑
循环依赖:feature A 依赖 feature B,B 又依赖 A。用接口或路由解耦。
构建变慢:模块数太多时,gradle 配置时间会增加。用 convention plugin 统一配置。
资源冲突:模块间同名资源会覆盖。命名规范加前缀。
导航复杂:多模块间页面跳转用 DeepLink 或 Navigation Component 的 include。
小结
模块化先按功能拆,再按需分层
Feature 模块之间不要直接依赖,用接口/路由
Dynamic Feature 适合大体积、低频功能
App Bundle 能减小用户实际下载体积
下一篇,我们进入工程质量:Android 测试金字塔与测试策略。
参考阅读
引用链接
[1]Android 模块化指南: https://developer.android.com/topic/modularization
[2]Dynamic Feature Modules: https://developer.android.com/guide/playcore/feature-delivery