一.说明
项目中使用了第三方框架以及对应后台不懂的接口环境,导致在不同的编译环境时要去手动替换很多配置文件,为了减少打包时间,决定通过gradle去替换配置环境。
二.Gradle Task
task顾名思义是一个任务,可以自定义自己想做的任务。
1. 创建task的方式
(1).使用task 后带任务名称 加上执行闭包{}
task t1{
println 't1'
}
(2).任务名称后加上圆括号
task t2() {
println 't2'
}
(3).在括号中命名的task
task ('t3'){
println 't3'
}
(4)doLast的task
task t4 << {
println "t4"
}
//以上定义的task等价于以下task
task t4 {
doLast{
println "t4"
}
}
2.task使用
(1).doFirst、doLast
task test{
println('test')
doFirst {
println('test doFirst')
}
doLast {
println('test doLast')
}
}
打印log如下:
test
test doFirst
test doLast
以上log输出可以看出,直接打印的test最先输出,doFirst先执行,doLast是后执行的,我们在自定义task时可以参考这个顺序去按实际情况使用,为什么是这个执行顺序后面简单介绍一下gradle构建周期。(doFirst和doLast属于执行阶段,println('test')属于配置阶段)。
3.常用系统提供task,拷贝
(1).常规拷贝task使用, 第一种可以拷贝指定文件,第二种可以批量拷贝指定目录里面的指定格式文件,例子如下:
task copyTask(type:Copy){
// 1.拷贝指定文件
// 待拷贝的路径
from 'src/app/123.txt'
// 拷贝文件目标路径
into 'build'
// 2.拷贝指定目录
// 待拷贝的路径
from 'src/app'
// 拷贝文件目标路径
into 'build'
// 过滤要拷贝的文件
include ('**/*.txt')
// 过滤不拷贝的文件
exclude ('**/*.java')
}
这种拷贝方式使用了系统定义的copytask,我在使用过程中无法控制拷贝的执行顺序,不能在doLast中拷贝,会报错,想控制执行顺序可以看第二种方法。
(2).当有时候我们想控制拷贝执行顺序,想再拷贝前后做一些事情的时候,可以使用另一种copy方法,可以不强校验,用法如下:
task copyTask {
doFirst {
}
doLast {
copy {
from project.rootDir.path + File.separator + 'mpaas-h5_json' + File.separator + buildEnvironment
into project.rootDir.path + File.separator + 'app/src/main/assets'
include('**/*.json')
}
}
}
这样写可以在拷贝前做一下事情,然后在doLast再去拷贝
4.项目中使用
项目中需要将对应的配置文件替换现有的配置文件,我将项目里使用的task贴一下,供大家参考一下:
//替换H5json.json的文件
task copyTask {
doFirst {
//2.删除mpass H5文件
println("copyTask2, delete h5_json.json ")
delete(project.rootDir.path + File.separator + 'app/src/main/assets/h5_json.json')
}
doLast {
println('copyTask2, buildEnvironment: ' + buildEnvironment)
println("copyTask2, h5_json.json ")
copy {
from project.rootDir.path + File.separator + 'mpaas-h5_json' + File.separator + buildEnvironment
into project.rootDir.path + File.separator + 'app/src/main/assets'
include('**/*.json')
}
}
}
// release环境task
task releasePropertyTask() {
group 'youlife:property task'
// 依赖
dependsOn(copyTask) {
println('------------------------releasePropertyTask start----------------')
buildEnvironment = 'release'
println('------------------------realsePropertyTask end-------------------')
}
}
项目中先删除文件再拷贝文件,避免环境切换文件替换不成功或覆盖失败,动态配置了环境变量buildEnvironment,在编译task执行时时根据buildEnvironment去动态配置,看我的文章时可以参考这种用法。
这里定义了两个task,用到了dependsOn依赖,在执行releasePropertyTask时先执行copyTask。具体dependsOn看下面的dependsOn的介绍。
5.dependsOn依赖介绍
(1).依赖顾名思义,是两个事物之间的依赖关系,task使用依赖时A依赖B的话,在执行taskA时会先执行task B后再执行A,举例代码如下:
task test1 << {
println "test1"
}
task test2 << {
println "test2"
}
task test3 << {
println "UI test"
}
test2.dependsOn test1
添加依赖后执行log如下:
test1
test2
(2).Gradle中的task之间的关系可以用有向无环图(DAG)来表示。任务之间不能互相依赖,否则Gradle会报错。
test2.dependsOn test1
test1.dependsOn test2
执行gradle unitTest会报错Circular dependency。
(3).没有依赖关系的任务之间可以通过mustRunAfter()、finalizedBy()等method来指定任务的执行顺序。举例如下:uiTest和unitTest都依赖于compile,那么如何保证uiTest总是在unitTest之后执行呢?答案就是使用mustRunAfter()。
test3.mustRunAfter test2
执行gradle uiTest unitTest -q会输出如下结果,说明unitTest是在uiTest之前运行的。
test1
test2
test3
6.gradle构建生命周期
上面讲的task以及一些依赖等都和gradle的构建生命周期是息息相关的,那么我们要了解一下,才能知道为什么task的执行顺序是这样的
(1).初始化
Gradle可以构建一个和多个项目。在初始化阶段,Gradle会确定哪些项目参与构建,并且为这些项目创建一个Project实例。
(2).配置
在这个阶段,会配置project对象。将执行构建的所有项目的构建脚本。也就是说,会执行每个项目的build.gradle文件。
(3).执行
Gradle确定要在执行期间创建和配置的任务子集。子集由传递给gradle命令和当前目录的任务名称参数确定。 Gradle然后执行每个选定的任务。
task执行周期:
1.不被任何方法包裹时,是在配置阶段运行
2.doFirst、doLast、拷贝from to等系统方法是在执行阶段运行
7.自动执行自定义task
可以在gradle配置阶段将编译task依赖于自定义的task,即可实现打包时自动运行自定义的task,项目中使用如下:
afterEvaluate {//gradle配置最后阶段回调
println('-----------------------afterEvaluatestart-------------------')
tasks.matching {//匹配
it.name.startsWith('pre') && it.name.endsWith('ReleaseBuild')
}.each { tk ->
tk.dependsOn(releasePropertyTask)
}
}
afterEvaluate是gradle配置最后阶段回调,可以在此处遍历所有的task,并且在匹配到指定的task时让其依赖自定义的task后,在执行preReleaseBuild任务之前会先执行releasePropertyTask,达到了自动化执行自定义的task的目的。