尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Product Flavors:从配置到最终 App 的完整过程

Product Flavors:从配置到最终 App 的完整过程 前面光讲了flavor 是什么和配置怎么写但你在 build.gradle 里写的那几行配置到底是怎么一步步变成一个个不同的 APK 的——这个过程没讲清楚。这篇专门补上把整条链路走一遍。先建立一个核心认知谁在读配置首先要搞清楚读你配置的人是 Gradle。你写在build.gradle里的东西本质上是一份给 Gradle 看的说明书。Gradle 是 Android 的构建工具它在你点击打包或运行./gradlew命令时启动第一件事就是读你的配置文件搞明白你到底想让我干什么。所以整个过程的起点是你写配置 → Gradle 读配置 → Gradle 按配置干活 → 产出 APK下面把中间Gradle 读配置、按配置干活这段一帧一帧拆开。第一步Gradle 读配置在脑子里列出所有变体假设你的配置是这样android{flavorDimensionsversionproductFlavors{free{dimensionversion}paid{dimensionversion}}buildTypes{debug{}release{}}}Gradle 启动后读到这段它做的第一件事是做乘法在内存里列出所有可能的组合Gradle 读到 flavor 有free、paid2个 buildType 有debug、release2个 Gradle 心算2 × 2 4于是它列出一张清单—— ┌─────────────────┐ │ freeDebug │ │ freeRelease │ │ paidDebug │ │ paidRelease │ └─────────────────┘这张清单就是变体Variant列表。此时还没开始真正打包Gradle 只是先把我能打出哪些包想清楚了。你在 Android Studio 的 Build Variants 面板里看到的下拉选项就是这一步的产物。第二步你选一个变体或命令行指定一个Gradle 不会一次把 4 个全打出来除非你让它这么做。通常你会指定要打哪一个。比如你在命令行敲./gradlew assembleFreeReleaseGradle 一看这个命令就明白了“哦从那张清单里你要的是 freeRelease 这一个。”于是它锁定目标这次只处理 free 这个 flavor release 这个 buildType 的组合。接下来所有的工作都围绕这一个变体展开。我们就跟着freeRelease这一个往下看它是怎么被组装出来的。第三步合并代码和资源目录关键步骤Gradle 确定了要打freeRelease现在它要收集这个包该包含哪些代码和资源。它会去合并这几个目录freeRelease 这个包 main 目录 free 目录 release 目录 公共 free专属 release专属具体过程是这样的Gradle我要打 freeRelease我去把这几个文件夹的东西拿来拼—— src/main/ ← 先拿公共的所有包都要的基础代码 ↓ src/free/ ← 再叠上 free 专属的只有免费版才有的东西 ↓ src/release/ ← 再叠上 release 专属的 ↓ 拼成一份完整的、只属于 freeRelease 的代码 资源关键在叠这个动作。如果 free 目录里有个strings.xml和 main 里同名那么free 的会覆盖 main 的。这就是为什么你能给免费版单独换个 App 名字src/main/res/values/strings.xml app_name 超级App src/free/res/values/strings.xml app_name 超级App(免费版) ↑ 打 freeRelease 时这个覆盖上面那个 最终包里 app_name 超级App(免费版)如果你现在打的是 paidReleaseGradle 就会去拿 paid 目录而不是 free 目录那么覆盖上去的就是付费版的名字了。同一套 main叠不同的 flavor 目录产出就不同——这就是 flavor 起作用的第一个机制。第四步处理配置字段生成 BuildConfig代码资源合并的同时Gradle 还会处理你写在 flavor 里的那些字段配置。假设你的 free flavor 里写了free{dimensionversionbuildConfigFieldboolean,SHOW_ADS,true}Gradle 打 freeRelease 时读到这一行会自动生成一个 Java 文件大概长这样// 这个文件是 Gradle 自动生成的你不用手写publicfinalclassBuildConfig{publicstaticfinalbooleanSHOW_ADStrue;// ← 来自 free 的配置// ...}注意时机这个 BuildConfig 是在编译时、根据当前打的变体生成的。打 freeRelease 时Gradle 读 free 的配置生成的SHOW_ADS true打 paidRelease 时Gradle 读 paid 的配置生成的SHOW_ADS false所以你代码里写的这句if(BuildConfig.SHOW_ADS){showAd();}在免费版里SHOW_ADS是 true走进去显示广告在付费版里是 false直接跳过。但你的这段代码本身一个字都没改——变的只是编译时被填进去的那个值。这就是配置驱动执行的核心你的逻辑代码是死的Gradle 根据当前变体把不同的值填进 BuildConfig从而让同一段代码表现出不同行为。第五步编译、打包、签名产出 APK材料都齐了合并好的代码资源 生成好的 BuildConfigGradle 进入最后阶段合并好的代码 → 编译成字节码 → 打包资源 → 打包成 APK → 用签名文件签名 ↓ app-free-release.apk最终吐出一个app-free-release.apk。这就是免费版的正式包。把整条链路连起来看现在把从头到尾串一遍你就能看到配置 → 执行的完整流动了① 你写配置 build.gradle 里定义 free/paid、SHOW_ADS 等 ↓ ② Gradle 读配置 启动构建读懂你的说明书 ↓ ③ 列出变体清单 做乘法free×paid × debug×release 4个变体 ↓ ④ 你指定一个 assembleFreeRelease → 锁定 freeRelease ↓ ⑤ 合并目录 main free releasefree覆盖main的同名资源 ↓ ⑥ 生成BuildConfig 读free的配置生成 SHOW_ADS true ↓ ⑦ 编译打包签名 产出 app-free-release.apk ↓ ⑧ 运行时 App里 if(BuildConfig.SHOW_ADS) 成立显示广告如果这次改成打 paidRelease只有 ④⑤⑥ 三步的选择变了——第④步锁定的是 paid第⑤步合并的是 paid 目录第⑥步生成的SHOW_ADS false。于是产出的付费版包运行时就不显示广告了。同一套代码同一套流程只因为选了不同的 flavorGradle 在关键的几步做了不同的选择最终就产出了不同的 App。这就是 flavor 从配置到执行的全部秘密。一句话收尾Product Flavors 从配置到执行的过程本质是你在 build.gradle 里声明有哪些口味和各口味的差异 → Gradle 读配置后列出所有变体组合 → 你指定打哪个变体 → Gradle 就为这个变体合并对应的目录、生成对应的 BuildConfig、填入对应的值 → 编译出这个口味专属的 APK。配置是说明书Gradle 是执行者变体是选择哪一份说明书。你写的业务代码始终不变变的只是 Gradle 在打包时根据 flavor 做出的一系列选择。这样看是不是就把配置怎么一步步变成不同 App这个过程串起来了
返回列表