1、前言
你是不是想过在根目录/build.gradle 根据一个变量来确定是否依赖某一个 classpath 阿?
举个我们项目中的栗子:因为我们的项目是国内外同一套代码,国外的会依赖谷歌相关的服务,而国内的不依赖谷歌服务。所以我想在 build.gradle 根据需要去依赖谷歌服务。
classpath 'com.google.gms:google-services:4.2.0'
2、出现问题
在 config.gradle 声明一个 channle 变量
//这里是 config.gradle
ext {
channel = 1//我们在这里定义一个变量channel,假设1表示海外市场的包
}
在根build.gradle 中依赖 config.gradle 然后根据 ext.channel 这个值来决定是否要依赖谷歌服务。
//这里是根目录下的build.gradle
apply from 'config.gradle'
buildscript {
dependencies {
...
if(project.ext.channel == 1){//判断是否要依赖谷歌服务
classpath 'com.google.gms:google-services:4.2.0'
}
}
}
上面这样的代码,我们是最容易想到的解决方案,但是当你运行起来的时却发现一个奇怪的事情,你会看到下面的错误日志
> Cannot get property 'channel' on extra properties extension as it does not exist
我们显然是已经在 config.gradle 中定义了 channel 这个变量了,但是为什么还是找不到呢?
3、探索1:监听根build.gradle配置完毕获取 channel 字段
apply from 'config.gradle'
project.afterEvaluate {
println "root project is afterEvaluate"
println "the channel is ${project.ext.channel}"
}
buildscript {
dependencies {
...
println "config google-services"
classpath 'com.google.gms:google-services:4.2.0'
}
}
可以看到日志, 在 afterEvaluate 中是可以拿到这个 channel 值的,那就可以排除我们ext写错的情况了。
那就有点奇怪了,进一步猜想,难道是因为执行顺序问题?
4、探索2:log验证执行顺序
apply from 'config.gradle'
println "apply from config.gradle"//输出1
project.afterEvaluate {
println "afterEvaluate the channel is ${project.ext.channel}"//输出2
}
buildscript {
dependencies {
...
println "config google-services"//输出3
classpath 'com.google.gms:google-services:4.2.0'
}
}
这时可以发现,执行的顺序分别是 输出3 -> 输出1 -> 输出2
哦嚯,果然是执行顺序的问题,这个有点坑了,对比 子build.gradle 都是按顺序从上往下执行了,在 根build.gradle 就有点不一样了,其实想想也有道理,因为这里会依赖一些 gradle 插件之类的,如果让其它的 gradle 先执行那就肯定有问题了。
5、解决方案
将 apply 相关的代码挪到 buildscript 这个闭包内就可以啦,代码如下所示
buildscript {
//将对应的外部依赖放到这里去依赖
apply from 'config.gradle'
dependencies {
...
if(project.ext.channel ==1){
classpath 'com.google.gms:google-services:4.2.0'
}
}
}
本文是笔者学习之后的总结,方便日后查看学习,有任何不对的地方请指正。
记录于 2020年3月21号