Gradle是一款非常优秀的构建系统工具,它是一门专门解决自动化构建的DSL(Domain Specifice Language,领域特定语言)。它的实现基于Groovy(Groovy是一种基于JVM虚拟机的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy它的语法和Java非常相似,能够与 Java 代码很好地结合和扩展)。
Gradle的官网下载页地址是:https://services.gradle.org/distributions/。一般地下载完后将其解压放于C:\Program Files\Android\gradle-x.x.x中,我们可以看到如下目录清单:
bin docs -- API、DSL、指南等文档 init.d -- gradle的初始化脚本目录 lib -- 相关库 media -- 一些icon资源 samples -- 示例 src -- 源文件 getting-started.html -- 入门链接 LICENSE NOTICE
要运行Gradle,必须把bin目录添加到环境变量PATH的路径里才可以。添加后要验证配置是否正常,我们只需要在命令窗口中输入gradle –v命令查看即可(若不行请重启电脑)。
新建一目录,如:gradle_hello_world,然后就该目录下创建一个名为build.gradle的文件,文件内容如下:
task hello{ doLast{ println'Hello World!' } }命令窗口中运行gradle –q hello命令来执行构造脚本,输出:
说明:
1、build.gradle就Gradle默认的构建脚本,执行Gradle命令时会默认加载当前目录下的build.gradle脚本文件。
2、这个脚本定义一个任务(Task),任务名叫hello,并且给任务hello添加一个动作(Action),其实它就是一段Groovy语言实现的闭包。doLast意味着在Task执行完毕后要回调doLast的这部分闭包的代码实现。
3、因为Groovy已经把println()方法添加到java.lang.Object,而在Groovy中,方法的调用可省略括号,以一个空格分开即可;还有一点,在Groovy中单引号和双引号的内容都是字答串,不区分字符和字符串,但是单引号标记的是纯粹字符串常量,而不能参与表达式运算。
4、命令gradle –q hello中,-q参数用于控制gradle输出的日志级别。gradle的日志级别有:
ERROR 错误信息 QUIET 重要消息 WARNING 警告消息 LIFECYCLE 进度消息 INFO 信息消息 DEBUG 调试信息
5、另外,除了日志级别参数外,还可以通过-s(关键性的堆栈信息)或-S(全部堆栈信息)来打印出堆栈信息
Wrappe是对Gradle的一层包装,便于团队开发过程中统一Gradle构建的版本。当我们使用Wrapper启动Gradle时,Wrapper会检查Gradle有没有被下载关联,如果没有将会配置的地址(一般是Gradle官方库)进行下载并运行构建。只要执行Wrapper命令,它会帮你搞定一切。这种方式也方便我们在服务器上做持续集成。
在命令窗口中输入:gradle wrapper(默认当前电脑版本) 或 gradle wrapper –gradle-version x.x(指定版本),便生成如下图文件:
文件说明:
文件gradlew和gradlew.bat分别是Linux和Windows下的可执行脚本,它们的用法和Gradle原生命令是一样的。
文件夹gradle下有两件文件:gradle\wrapper\gradle-wrapper.jar 和 gradle\wrapper\gradle-wrapper.properties。其中,gradle-wrapper.jar是具体业务逻辑实现的jar包,gradlew最终还是使用Java执行这个jar包来执行相关Gradle操作,而gradle-wrapper.properties是配置文件,用于配置Gradle信息。
gradle-wrapper.properties它的内容如下图所示:
配置中字段说明:
distributionBase 下载的Gradle压缩包解压后存储的主目录 distributionPath 相对于distributionBase的解压后的Gradle压缩包的路径 zipStoreBase 同distributionBase,只不过是存放zip压缩包的 zipStorePath 同distributionPath,只不过是存放zip压缩包的 distributionUrl Gradle发行版压缩包的下载地址。通常地会将distributionUrl 中的bin改为all,这样在开发过程中,就可以看到Gradle的源代码。另外,如若总是下载失败,可以考虑将https替换成http。
也可以通过task来自定义gradle-wrapper.properties的字段信息,如个修改build.gradle文件,并运行命令:gradle wrapper
task hello{ doLast{ println'Hello World!' } } task wrapper(type:Wrapper) { gradleVersion = '4.2.1' archiveBase='GRADLE_USER_HOME' archivePath='wrapper/dists' distributionBase='GRADLE_USER_HOME' distributionPath='wrapper/dists' distributionUrl='http://services.gradle.org/distributions/gradle-4.2.1-all.zip' }Groovy中,分号是可写可不写的。
Groovy中,单引号和双引号都可以定义字符串常量,不同的是单引号标记的是纯粹字符串常量,而不是对字符串里的表达式做运算,但双引号可以。如使用“+”连接两个字符串,就一定得使用双引号。
Groovy中,使用ArrayList就像使用普通数组一样,修改hello world示例代码如下:
task hello{ println'Hello World!' def numList = [1,2,3,4,5]; println'----------ArrayList class name:' println numList.getClass().name; println'----------ArrayList element:' println numList[1] // 访问第二个元素 println numList[-1] // 访问最后一个元素 println numList[0..2] // 访问第1到第3个元素 println'----------ArrayList each:' numList.each{ println it; } }运行结果:
来看看map的使用示例,同样修改hello world示例代码如下:
task hello{ println'Hello World!' def mapSizp = ['width':1920, 'height': 1080]; println'----------LinkedHashMap class name:' println mapSizp.getClass().name; println'----------LinkedHashMap element:' println mapSizp['width']; println mapSizp.height; println'----------LinkedHashMap each:' mapSizp.each{ println "Key:${it.key},Value:${it.value}"; } }运行结果:
方法的写法很有意思,括号是可以省略的,return可写可不写,请看示例:
task hello{ println'Hello World!' def a = compute(1, 2) println a def b = compute 3, 4 println b } def compute(int a, int b) { // return a + b; a + b; }一段被大括号包括的代码称为闭包或代码块。Groovy中是允许其作为参数传递的,像上面使用到的集合each方法为例,它接收的参数其实就是一个闭包:
// 呆板的写法 numList.each({ println it }) // 格式化后 numList.each( { println it }) // 如果方法的最后一个参数是闭包,可以放在方法外面 numList.each() { println it } // 方法是可以省备括号的 numList.each { println it }来自定义一个闭包作参数传递的示例:
task hello{ customEach { println it } } def customEach(closure) { for(int i in i..10) { closure(i) } }说明:
当定义的方法只接收一个参数,用于接收一个闭包时,那么就可以默认使用it变量
向闭包传递参数示例:
task hello{ customEach2{k, v -> println "${k} is ${v}" } } def customEach2(closure) { def mapSize = ["width":1920, "height":1080] mapSize.each { closure(it.key, it.value); } }说明:
当闭包需要传递参数时,就不再使用it了,必须显式声明出来。
Groovy的闭包有thisObject、owner、delegate三个属性,当闭包内调用方法时,由它们来确定使用哪个对象来处理。示例:
task hello{ new Delegate().test { println "thisObject:${thisObject.getClass()}" println "owner:${owner.getClass()}" println "delegate:${delegate.getClass()}" methodl(); it.methodl(); } } def methodl() { println "Context this:${this.getClass()} in root" } class Delegate { def methodl() { println "Delegate this:${this.getClass()} in Delegate" } def test(Closure<Delegate> closure) { closure(this) } }输出结果:
thisObject:class build_eglgh8qvzzqz0eqp07enfojra
owner:class build_eglgh8qvzzqz0eqp07enfojra$_run_closure1
delegate:class build_eglgh8qvzzqz0eqp07enfojra$_run_closure1
Context this:class build_eglgh8qvzzqz0eqp07enfojra in root
Delegate this:class Delegate in Delegate
说明:
thisObject的优先级最高,delegate和owner是相等的,但owner要比delegate优化级高。
delegate是可以被修改的,Gradle中的闭包很多功能都是通过修改delegate来实现的,详细使用在后面介绍
Gradle创建任务的方式有多种
第一种,任务名字+闭包配置的方式(我们在上面看到的方式)
task hello{ doLast{ println'Hello World!' } }第二种,变量方式,task(String name)方法接收一个任务名作为参数,然后赋予变量
def Task taskHello = task(hello) taskHello.doLast{ println'Hello World!' }任务是可以分组的和添加描述的,这样就是便于我们对任务进行归类整理,建议大家在创建任务时都要进行这两个属性的配置,以便于团队开发时别人能清楚知道该任务的分类和用途。示例:
def Task taskHello = task(hello) taskHello.group = BasePlugin.BUILD_GROUP taskHello.description = '我是hello任务' taskHello.doLast{ println'Hello World!' }或者
def Task taskHello = task(hello, group:BasePlugin.BUILD_GROUP, description:'我是hello任务') taskHello.doLast{ println'Hello World!' }“<<”操作符在Gradle的Task上是doLast方法的知标记形式,所以上述示例也可以写成:
def Task taskHello = task(hello, group:BasePlugin.BUILD_GROUP, description:'我是hello任务') taskHello <<{ println'Hello World!' }通过shouldRunAfter和mustRunAfter两个方法可以控制一个任务应该或者一定在某个任务之后执行。
taskB. shouldRunAfter(taskA) 表示taskB应用在taskA执行之后执行,但这里是应该,所以有可能并不会按预设的执行
taskB. mustRunAfter (taskA) 表示taskB一定在taskA执行之后执行。
除了使用方法进行任务间改变执行顺序外,还可以使用任务依赖关系。示例:
task taskA << { println 'This is taskA' } task taskB(dependsOn: taskA) << { println 'This is taskB' } task taskC { dependsOn taskB // 多个可用逗号分隔 doLast { println 'This is taskC' } }说明:
在创建taskB任务时,可通过dependsOn 指写其依赖的任务在taskC任务执行时,也可以通过另外的方式让其依赖taskB当执行命令:gradle –q taskC后,输出结果应该是:This is taskA
This is taskB
This is taskC
