Settings 文件
在 Gradle
中,定义了一个设置文件,用于初始化以及工程树的配置。设置文件的默认名字是 settings.gradle
,放在根工程目录下。设置文件大多数的作用都是为了配置子工程。在 Gradle
中多工程是通过工程树表示的,就相当于我们在 Android Studio
看到的 Project
和 Module
概念一样。根工程相当于 Android Studio
中的 Project
,一个根工程可以有很多子工程,也就是很多 Module
,这样就和 Android Studio
定义的 Module
概念对应上了。一个子工程只有在 Settings
文件里配置了 Gradle
才会识别,才会在构建的时候被包含进去。
rootProject.name = 'GradleTest'
include ':example02'
project(':example02').projectDir = new File(rootDir, 'chapter01/example02')
上例这就是我们示例工程的 setting
配置,可以看到我定义了很多子项目,并且为它们指定了相应的目录,如果不指定,默认目录是其同级的目录。比如 include: example02
,如果我不指定, Gradle
就会把当前同级的 example02
目录作为 example02
工程的目录,但是没有这个目录,就会报错。利用这个特性,我们可以把我们的工程放到任何目录下,可以非常灵活地对我们的工程进行分级、分类等,只要 Settings
文件里指定好路径就可以了。
Build 文件
每个 Project
都会有一个 Build
文件,该文件是该 Project
构建的入口,可以在这里针对该 Project
进行配置,比如配置版本,需要哪些插件,依赖哪些库等。既然每个 Project
都会有一个 Build
文件,那么 Root project
也不例外。 Root project
可以获取到所有的 Child Project
,所以在 Root Project
的 Build
文件里我们可以对 Child Project
统一配置,比如应用的插件,依赖的 Maven
中心库等。
Projects 以及 tasks
在 Gradle
中,可以有很多 Project
,你可以定义创建一个 Project
用于生成一个 jar
,也可以定义另外一个 Project
用于生成一个 war
包,还可以定义一个 Project
用于发布上传你的 war
等。其实一个 Project
就是在你的业务范围内,被你抽象出来的一个个独立的模块,你可以根据项目的情况抽象归类,最后这一个个的 Project
组成了你的整个 gradle
构建。从我们编程的角度讲,它就是一个个独立的模块。好好利用它们,这样你的代码就能够做到低耦合、高内聚。
一个 Project
又包含很多个 Task
,也就是说每个 Project
是由多个 Task
组成的。Task
就是一个操作,一个原子性的操作,比如打个 jar
包,复制一份文件,编译一次 Java
代码,上传一个 jar
到 Maven
中心库等,这就是一个 Task
,和 Ant
里的 Target
, Maven
中的 goal
是一样的。
创建一个任务
task customTask {
doFirst {
println 'customTask:doFirst'
}
doLast {
println 'customTask:doLast'
}
}
这里的 Task
看着像一个关键字,其实它是 Project
对象的一个函数,原型为 create(Sting name, Closure configure Closure)
。 customTask
为任务的名字,我们可以自定义;第二个参数是个闭包,也就是我们花括号里的代码块。根据我们前面讲的 Groovy
知识,最后一个参数是闭包的时候,可以放到括号外面,然后方法的括号可以省略,就生成了我们上面的写法,很简洁。该闭包的作用就是用来对我们创建的任务进行配置,例子中我们用了任务的 dofirst
和 dolast
方法,分别在任务执行前后输出一段文字。
除了上面的方法,我们还可以通过 TaskContainer
创建任务。在 Gradle
中,Project
对象已经帮我们定义好了一个 TaskContainer
,就是 tasks
。
tasks.create ('customTask2'){
doFirst {
println 'customTask:doFirst'
}
doLast {
println 'customTask:doLast'
}
}
这种创建任务的方法跟上一种效果是一样的,只是名字不一样。
任务依赖
任务之间是可以有依赖关系的,这样我们就能控制哪些任务先于哪些任务执行;哪些任务执行后,其他任务才能执行。比如我们运行 jar
任务之前, compile
任务一定要执行过,也就是 jar
依赖于 compile
; Android
的 install
任务一定要依赖 package
任务进行打包生成 apk
,然后才能 install
设备里。
task test2 << {
println 'test2'
}
task test(dependsOn: test2){
doLast {
println 'test'
}
}
在创建任务的时候,通过 dependsOn
可以指定其依赖的任务。
task test2 << {
println 'test2'
}
task test(dependsOn: test2){
doLast {
println 'test'
}
}
task test3 {
dependsOn test,test2
doLast {
println 'test3'
}
}
dependsOn
是 Task
类的一个方法,可以接收多个依赖的任务作为参数。同时我们也可以使用 Task
的 API
访问它的方法属性或者对任务重新配置。
task ex36Hello << {
println 'dowLast1'
}
ex36Hello.doFirst {
println 'dowFirst'
}
ex36Hello.doLast {
println project.hasProperty('ex36Hello')
println 'dowLast2'
}
和变量一样,要使用任务名操纵任务,必须先定义声明,因为脚本是顺序执行的。运行上述代码后:
由结果可知,Project
在创建任务的时候,同时把该任务对应的任务名注册为 Project
的一个属性,类型是 Task
。
自定义属性
Project
和 Task
都允许用户添加额外的自定义属性,要添加额外的属性,通过应用所属对应的 ext
属性即可实现。添加之后可以通过 ext
属性对自定义属性读取和设置,如果要同时添加多个自定义属性,可以通过 ext
代码块:
//自定义一个Project的属性
ext.age = 18
//通过代码块同时自定义多个属性
ext{
phone = 183207612
address = 'nanshan'
}
task hello << {
println "年龄是:${age}"
println "电话是:${phone}"
println "地址是:${address}"
}
在我们的项目中一般使用它来自定义版本号和版本名称,把版本号和版本名称单独放在一个 Gradle
文件中。因为它们每次发布版本都会改变,变动频繁,放到一个单独的 Gradle
文件中,便于管理,而且改动的时候也不会因为 Git
冲突影响整个 Buid
文件,便于解决冲突。
脚本即代码 代码也是脚本
虽然我们在一个 Gradle
文件中写脚本,但是我们写的都是代码,这一点一定要记清楚,这样你才能时刻使用 Groovy
、Java以及
Gradle
的任何语法和 API
帮你完成你想做的事情。在这脚本文件上你可以定义 Class
内部类、导入包、定义方法、常量、接口、枚举等。
我们在项目中需要给生成的 APK
包以当前日期的格式命名,我们就定义了一个获取日期格式的方法,用于生成 APK
的文件名:
def buildTime(){
new Date().format('yyyyMMdd')
}
这只是使用的一个例子,目的是让大家灵活搭配 Java
、 Groovy
和 Gradle
,不要把它当成普通的脚本文件。