系列三组件化与模块化进阶 | 第9篇组件化架构从零搭建实战Gradle 极速配置、编译加速与多环境管控阅读警告本文为超深度技术长文预计阅读时长 40-60 分钟代码量极大。在第8篇中我们完成了组件化的物理拆分和路由通信。但仅仅拆开是不够的。如果你发现拆完后编译反而更慢了或者打包时各个组件的环境变量乱成一团那是因为你没有做好Gradle 工程化治理。这一篇我们将深入 Android 构建系统的腹地解决编译速度慢、依赖冲突、多环境混乱、多渠道包体积大等四大核心痛点。全文包含Gradle Kotlin DSL 迁移、Version Catalog 统一依赖、Configuration Cache 实战、多环境资源配置、以及美团 VasDolly 极速多渠道打包方案。1 引子组件化后的“构建之痛”很多团队在拆完组件后会面临一个新的困境“拆得快编得慢”。1.1 症状诊断编译时间不减反增以前单工程编译 5 分钟拆成 20 个组件后编译变成了 15 分钟。因为 Gradle 要处理更多的 Module 依赖解析。依赖地狱组件 A 用了 Glide 4.12组件 B 用了 Glide 4.15组件 C 用了老版本的 Support Library。运行时发生ClassNotFoundException或Method Not Found。环境混乱测试同学拿着包说“这是测试环境吗”你一看接口地址是正式环境的。因为各个组件里的BASE_URL没有统一。多渠道打包慢打 10 个渠道包要 1 个小时因为要全量编译 10 次。1.2 企业级构建优化目标指标优化前优化后全量编译15 分钟 3 分钟增量编译5 分钟 30 秒依赖冲突频繁发生零发生统一管控环境切换改代码/重打包动态配置/一键切换渠道打包1 小时 5 分钟2 Gradle 现代化Kotlin DSL Version Catalog还在用 Groovy 写build.gradle是时候升级了。Groovy 是动态语言IDE 提示弱重构难。企业级项目必须使用Kotlin DSL。2.1 迁移到 Kotlin DSL步骤 1重命名文件。build.gradle→build.gradle.ktssettings.gradle→settings.gradle.kts步骤 2修改settings.gradle.kts。// settings.gradle.ktspluginManagement{repositories{google()mavenCentral()gradlePluginPortal()}}dependencyResolutionManagement{repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories{google()mavenCentral()maven{urluri(https://jitpack.io)}}}rootProject.nameEnterpriseAppinclude(:app-shell)include(:component-login)include(:component-home)include(:module-base)步骤 3修改build.gradle.kts以module-base为例。// module-base/build.gradle.ktsplugins{id(com.android.library)id(org.jetbrains.kotlin.android)}android{namespacecom.example.module.basecompileSdk34defaultConfig{minSdk21targetSdk34}buildTypes{release{isMinifyEnabledfalseproguardFiles(getDefaultProguardFile(proguard-android-optimize.txt),proguard-rules.pro)}}}dependencies{implementation(androidx.core:core-ktx:1.12.0)implementation(androidx.appcompat:appcompat:1.6.1)}2.2 Version Catalog依赖统一管理的终极方案不要再在各个 Module 里写版本号了Gradle 7.0 提供了Version Catalog这是官方推荐的统一依赖管理方式。步骤 1创建gradle/libs.versions.toml。[versions] kotlin 1.9.20 agp 8.2.0 compose 1.5.4 material 1.11.0 glide 4.16.0 [libraries] androidx-core-ktx { group androidx.core, name core-ktx, version.ref kotlin } androidx-appcompat { group androidx.appcompat, name appcompat, version 1.6.1 } material { group com.google.android.material, name material, version.ref material } glide { group com.github.bumptech.glide, name glide, version.ref glide } [plugins] android-application { id com.android.application, version.ref agp } android-library { id com.android.library, version.ref agp } kotlin-android { id org.jetbrains.kotlin.android, version.ref kotlin }步骤 2在build.gradle.kts中使用。// module-base/build.gradle.ktsplugins{alias(libs.plugins.android.library)alias(libs.plugins.kotlin.android)}dependencies{implementation(libs.androidx.core.ktx)implementation(libs.androidx.appcompat)implementation(libs.material)implementation(libs.glide)}收益版本唯一所有 Module 强制使用同一个版本。升级方便只改toml文件不用动业务代码。IDE 支持点击跳转重构安全。3 编译加速从 15 分钟到 1 分钟这是本篇最核心的干货。Gradle 提供了多种加速手段你必须全部打开。3.1 Configuration Cache配置缓存痛点Gradle 每次编译都要重新配置 Task 依赖图非常耗时。解法Configuration Cache 把配置结果缓存起来。开启方式在gradle.properties中添加org.gradle.configuration-cachetrue org.gradle.configuration-cache.problemswarn效果第二次编译时跳过配置阶段直接执行 Task。3.2 Build Cache构建缓存痛点A 组件编译过的产物B 组件依赖它时还要再编译一次。解法Build Cache 把编译产物如 AAR缓存起来。开启方式org.gradle.cachingtrue3.3 Parallel Execution并行编译痛点Gradle 默认串行执行 Task。解法开启并行。org.gradle.paralleltrue3.4 守护进程Daemon确保开启默认开启org.gradle.configureondemandtrue3.5 Kotlin 增量编译确保 Kotlin 插件开启了增量编译默认开启tasks.withTypeKotlinCompile().configureEach{kotlinOptions{incrementaltrue}}3.6 实战优化前后的对比假设有 20 个 Module。优化手段全量编译时间无优化15 min Configuration Cache10 min Build Cache7 min Parallel5 min Kotlin 增量3 min最终效果冷编译 3 分钟热编译改一行代码30 秒。4 依赖隔离与冲突解决组件化后依赖冲突是最大的坑。4.1 依赖传递规则规则基础模块用implementation业务组件用api谨慎。implementation依赖只在当前 Module 可见不传递给上游。推荐api依赖会传递给上游。慎用容易导致依赖爆炸错误示范// component-login/build.gradle.ktsdependencies{api(libs.glide)// 错误所有依赖 login 的组件都会间接依赖 Glide}正确示范dependencies{implementation(libs.glide)// 只有 login 组件能用}4.2 统一第三方库版本通过Version Catalog我们已经解决了。4.3 排除冲突Exclude有时第三方库会引入冲突的依赖。dependencies{implementation(libs.some.sdk){exclude(groupcom.google.android,modulesupport-v4)}}5 多环境配置Dev / Test / Prod组件化后每个组件都有自己的BuildConfig。如何统一管理5.1 方案一Gradle 多 Flavor推荐步骤 1在壳工程和所有组件中定义 Flavor。// app-shell/build.gradle.ktsandroid{flavorDimensionsenvproductFlavors{create(dev){dimensionenvbuildConfigField(String,BASE_URL,\http://dev.api.com\)buildConfigField(boolean,LOG_DEBUG,true)}create(test){dimensionenvbuildConfigField(String,BASE_URL,\http://test.api.com\)buildConfigField(boolean,LOG_DEBUG,true)}create(prod){dimensionenvbuildConfigField(String,BASE_URL,\https://api.com\)buildConfigField(boolean,LOG_DEBUG,false)}}}步骤 2组件中同步配置使用publishNonDefault确保依赖正确。// component-login/build.gradle.ktsandroid{flavorDimensionsenvproductFlavors{create(dev){dimensionenv}create(test){dimensionenv}create(prod){dimensionenv}}}步骤 3代码中使用。// 任何组件中if(BuildConfig.LOG_DEBUG){Log.d(TAG,Debug Mode)}Retrofit.Builder().baseUrl(BuildConfig.BASE_URL).build()打包命令./gradlew assembleDevDebug ./gradlew assembleProdRelease5.2 方案二使用buildConfigField动态切换如果不想用 Flavor因为 Flavor 会导致变体爆炸可以用 BuildConfig 字段。在gradle.properties中定义ENV_TYPEdev在build.gradle.kts中读取valenvTypeproject.findProperty(ENV_TYPE)?:devandroid{buildTypes{release{buildConfigField(String,ENV_TYPE,\$envType\)}}}6 多渠道打包极速方案传统的多渠道打包在 Manifest 中写占位符需要编译多次。我们要用美团 VasDolly或腾讯 ApkChannelPackage实现一次编译多次写入渠道。6.1 集成 VasDolly步骤 1根目录build.gradle.kts。buildscript{dependencies{classpath(com.meituan.android.walle:plugin:1.1.7)}}步骤 2壳工程app-shell/build.gradle.kts。plugins{id(com.android.application)id(walle)}walle{// 指定渠道包的输出路径apkOutputFolderfile(${project.buildDir}/outputs/channels)// 指定渠道配置文件channelFilefile(channel.txt)}步骤 3创建channel.txt。xiaomi huawei oppo vivo yingyongbao步骤 4打包。./gradlew clean assembleReleaseChannels效果只编译一次 Release 包瞬间生成 5 个渠道包。6.2 代码中获取渠道importcom.meituan.android.walle.WalleChannelReaderclassAppShell:Application(){overridefunonCreate(){super.onCreate()valchannelWalleChannelReader.getChannel(this)Log.d(App,Channel:$channel)}}7 包体积优化组件化必做组件多了包体积容易变大。7.1 开启资源缩减buildTypes{release{isMinifyEnabledtrueisShrinkResourcestrue// 移除无用资源proguardFiles(getDefaultProguardFile(proguard-android-optimize.txt))}}7.2 图片压缩与 WebP所有 PNG 转为 WebP。使用 TinyPNG 压缩。7.3 动态下发非首屏必须的组件如客服、反馈考虑使用动态下发Dynamic Feature Module或插件化。8 企业级 Gradle 配置模版直接复制用这是经过大厂验证的gradle.properties配置# 基础配置 org.gradle.jvmargs-Xmx4096m -Dfile.encodingUTF-8 org.gradle.configureondemandtrue org.gradle.paralleltrue org.gradle.cachingtrue # 关键Configuration Cache org.gradle.configuration-cachetrue org.gradle.configuration-cache.problemswarn # Android android.useAndroidXtrue android.enableJetifiertrue android.nonTransitiveRClasstrue # Kotlin kotlin.incrementaltrue kotlin.caching.enabledtrue9 总结构建系统的“军规”统一工具链Kotlin DSL Version Catalog。必须开缓存Configuration Cache Build Cache。依赖要收敛基础模块implementation禁止滥用api。环境要隔离Flavor 管理 Dev/Test/Prod。渠道要极速VasDolly 一次编译多渠道。至此我们的组件化架构已经具备了物理隔离代码不耦合通信解耦路由构建极速Gradle 优化环境可控多 Flavor发布高效多渠道下一篇预告系列三组件化与模块化进阶 | 第10篇组件通信与路由ARouter 核心落地我们将深入 ARouter 的源码讲解跨组件服务调用Service Provider、降级策略、以及路由表的动态更新。如果你的项目编译还在 10 分钟以上请立即执行本文的优化方案。这不仅是技术优化更是对团队生命的尊重。