阅读本篇内容请先了解Gradle Project的相关概念
深入理解Gradle项目构建,你需要知道这些
关于gradle project的其实你可以理解为build.gradle。一个build.gradle就代表一个project。
一、task定义
下面讲述一下关于Task的概念:
task其实里可以理解成gradle project的构建单元,Android代码编译其实就是执行一个个task任务。通过./gradlew tasks
命令当前的project下有多少个task。下面来看一下task如何定义:
第一种方式,直接通过task函数定义
task mytask{
println "我是一个task任务"
}
可以通过源码直接了解如何创建
/**
* <p>Creates a {@link Task} with the given name and adds it to this project. Calling this method is equivalent to
* calling {@link #task(java.util.Map, String)} with an empty options map.</p>
* @param name The name of the task to be created
* @return The newly created task object
*/
Task task(String name) throws InvalidUserDataException;
执行验证一下
dsh$ ./gradlew mytask
我是一个task任务
第二种方式,使用tasks容器创建
this.tasks.create(name:"mytask2"){
println "我是mytask2任务"
}
执行一下
dsh$ ./gradlew mytask2
我是一个task任务
我是mytask2任务
从执行结果上看第二种创建方式也是可行的,但是细心的同学可能很好奇,为什么执行./gradlew mytask2
打印输出了mytask里的输出了呢?原因是执行task的时候,会经历一段配置阶段,我们的打印语句都在配置阶段被执行了。怎样让我们的打印语句执行在task的执行阶段呢?下面介绍的两个方法就可以做到doFirst
和 doLast
。
this.tasks.create(name:"mytask2"){
println "我是mytask2任务"
doFirst {
//该任务执行前被执行
println "我是mytask2任务 doFirst"
}
doLast {
//该任务执行后执行
println "我是mytask2任务 doLast"
}
}
执行一下
localhost:GradleStudy dsh$ ./gradlew mytask2
初始化阶段开始啦。。。。
> Configure project :app
我是一个task任务
我是mytask2任务
> Task :app:mytask2
我是mytask2任务 doFirst
我是mytask2任务 doLast
可以看到我们的doFirst和doLast执行的时间是在gradle的执行阶段执行的。
下面写一个案例来加深对task的理解
计算编译期间所有task执行的时间
this.afterEvaluate { project ->
def preBuildTask = project.tasks.getByName("preBuild")
def startTime
def endTime
preBuildTask.doFirst {
startTime = System.currentTimeMillis()
}
def buildTask = project.tasks.getByName("build")
buildTask.doLast {
endTime = System.currentTimeMillis()
}
println "编译期间所有task执行用时 ${startTime - endTime}"
}
执行一下
./gradlew build
> Task :app:preBuild
编译期间开始时间 1525958501917
> Task :app:lint
> Task :app:build
编译期间所有task执行用时 11047
二、task的执行顺序
1、dependsOn强依赖的方式
定义3个task
task task1{
setGroup("study")
doLast{
println "执行了task1"
}
}
task task2{
setGroup("study")
doLast{
println "执行了task2"
}
}
task task3(dependsOn:[task2,task1]){
setGroup("study")
doLast{
println "执行了task3"
}
}
执行一下
./gradlew task3
> Task :task1
执行了task1
> Task :task2
执行了task2
> Task :task3
执行了task3
通过上面的打印可以知道,task3 的执行依赖于task1 和2,所以通过dependsOn
改变task的执行顺序。
下面写一个小程序练习一下
//将当前project目录下的releases的每个子节点的内容解析到generated/release/以文件的形式保存
task handleRelease {
def soureceFile = file("releases.xml")
def destDir = new File(this.buildDir,"generated/release/")
doLast {
if (!destDir.exists()) {
destDir.mkdir()
}
def releases = new XmlParser().parse(soureceFile)
releases.release.each { releaseNode ->
//解析节点内容
def versionCode = releaseNode.versionCode.text()
def versionName = releaseNode.versionName.text()
def versionInfo = releaseNode.versionInfo.text()
//创建文件并写入节点数据
def destFile = new File(destDir,"release-${versionName}.txt")
destFile.withWriter {writer->
writer.write("${versionCode}+${versionName}+${versionInfo}")
}
}
}
}
//利用dependsOn 执行我们解析xml的task任务
task testHandleRelease(dependsOn:[handleRelease]){
doLast{
def dir = fileTree(this.buildDir.path+"generated/release/")
dir.each {
println "this file is ${it}"
}
}
}
2、通过输入输出的方式指定
TaskInputs
和TaskOutputs
————–2018-05-10———————–