一、什么是 Groovy
1. 官网:
2. 概念:
是基于 JVM 虚拟机的一种动态语言,语法上和 Java 非常相似,完全兼容 Java,可以说是一门非常灵活的动态脚本语言
3. 应用:
Gradle 的 build 脚本文件都是一个 Groovy 脚本文件,是使用 Groovy 进行编写的
二、基础语法
由于我们是在学习 Gradle 尤其是 Android Gradle,所以一开始对于 Groovy 不需要掌握得非常深刻,我们这里就对一些语法概念稍作学习,目的是可以读懂 Gradle 相关脚本文件的一些代码和编写简单的脚本文件,等 Gradle 学习深入后再去了解 Groovy 的高级特性。
1. 如何定义一行代码的结束
Groovy 中,每一行的结束不是一定要用分号的,直接换行即可,当然也可以保持 Java 习惯,写上分号
2. 定义标识符
def 是 Groovy 用来定义标识符的关键字
// 定义一个字符串变量 nicholas 它的值为 hzf
def nicholas = "hzf";
// 定义一个方法 buildString,接收两个字符串参数,返回它们拼接的结果
def buildString(String a, String b){
println "$a-$b"
}
3. 方法
A.)括号可省略: 调用方法的时候,可以省略括号,如 #2
task methodTest {
buildString("Nicholas","hzf") // #1
buildString "Nicholas","hzf" // #2
}
def buildString(String a, String b){
println "$a-$b"
}
B.)return 可不写: 方法中没有写 return 语句,则方法执行过程中的最后一句代码的值作为返回值
task methodTest {
def result = chooseSmallNum 1,10
println result
}
def chooseSmallNum(int a, int b){
if (a <= b) {
a
}else {
b
}
}
C.)代码块可作为参数传递
代码块: 代码块就是闭包,通俗来说就是一段被大括号包裹起来的代码
演化:
#1 是初始写法,比较繁琐
#2 Groovy 规定如果方法的最后一个参数是闭包,可以放到方法后面
#3 刚才说到方法调用时,括号可以省略,所以综上三种写法都是可以的,最为常见的是 #3 这种写法,了解完转化写法后就会觉得直观又简洁
task methodTest3 {
doSomething("Nicholas0","hzf",{a,b -> println "$a-$b"}) // #1
doSomething("Nicholas1","hzf"){ a,b -> // #2
println "$a-$b"
}
doSomething "Nicholas2","hzf",{ a,b -> // #3
println "$a-$b"
}
}
def doSomething(String a, String b, Closure method){ // Closure 定义闭包
method.call(a,b) // call 调用闭包
}
4. JavaBean
在 Groovy 中,并不是一定要定义成员变量才可以作为一个类的属性进行访问,只要写了 getter/setter 方法,也一样可以作为属性进行访问。如果只写了 getter 方法,那不可以修改该属性的值,如例子中的 age 属性;反之,如果只写了 setter 方法,那就无法访问到这个属性
task javaBeanTest {
Person p = new Person()
// Groovy 中的 private 定义的属性竟然可以直接访问!!!
p.name = "Nicholas"
println p.info
}
class Person {
private String name;
public int getAge(){24}
public setInfo(String info){}
public String getInfo(){
"$name-$age"
}
}
5. 字符串
Groovy 中提供了三种表示 String 的方法:单引号(’),双引号(")或三引号(’’’)括起来。其中,单引号括起来的字符串没有运算能力,如 #1 所示 $strB 原模原样的打印出来了;由三引号括起来的字符串可以跨越多行
task stringTest {
def strA = '单引号'
def strB = "双引号"
def strC = '''
---三引号---
'''
println strA
println strB
println strC
println '单引号==$strB' // #1
println "双引号==$strB"
println '''三引号==$strC'''
}
6. 集合
对于 List 来说,Groovy 提供下标索引的方式进行访问,值得注意的是,除了普通的下标索引,还有负下标索引和范围索引的方式
task listTest{
def nameList = ["Nicholas","hzf","Groovy","Java","Kotlin","Android","Gradle"]
println nameList[0] // 正数第一个
println nameList[1] // 正数第二个
println nameList[-2] // 倒数第二个
println nameList[-1] // 倒数第一个
println nameList[0..2] // 正数第一个到第三个
println nameList[-1..1] // 倒数第一个到正数第二个,倒着打印
}
7. 闭包
A.)概念: 由大括号括起来的一段代码
下面例子中的 {println it}
与 {k,v -> println "$k-$v"}
都是闭包
task closureTest{
// listEach 的参数是闭包
// 即 {println it}
listEach {
println it // 闭包只有一个参数的时候,默认就是 it
}
// mapEach 的参数是闭包
// 即 {k,v -> println "$k-$v"}
mapEach { k,v ->
println "$k-$v" // 闭包不只一个参数的时候,需要把参数一一列出
}
}
// 方法 listEach 只有一个参数,用于接收一个闭包参数
def listEach(closure){
def nameList = ["Nicholas","hzf","Groovy","Java","Kotlin","Android","Gradle"]
nameList.each {
closure(it)
}
}
// 方法 mapEach 只有一个参数,用于接收一个闭包参数
def mapEach(closure){
def map = ["Nicholas":"hzf","Gradle":"Groovy","Android":"Kotlin"]
map.each {
closure(it.key,it.value)
}
}
B.)闭包委托
- 闭包的三个属性:thisObject,owner,delegete 在闭包内调用方法时,由这三个参数决定使用哪个对象来调用这个被调用的方法:比如说,闭包内执行了方法 A(),那这个 A() 是脚本中的方法 A,还是某个类中的方法 A
- thisObject 构建脚本的上下文,和脚本中的 this 相等
- 默认情况下 delegete 与 owner 是相等的,但是 delegete 可以被修改,修改后就和 owner 不相等了
- 闭包方法内处理的顺序:thisObject > owner > delegete
- 在 Gradle 中,一般指定 delegate 为当前的 it
task closureTest2{
createBook {
bookName = "Android Gradle 权威指南"
author = "飞雪无情"
pageNum = 236
dumpBook()
}
}
class Book{
String bookName
String author
int pageNum
def dumpBook(){
println "in dumpBook bookName==$bookName, pageNum==$pageNum, author$author"
}
}
def createBook(Closure<Book> closure){
Book book = new Book()
closure.delegate = book
closure.setResolveStrategy(Closure.DELEGATE_FIRST)
closure(book)
}
def dumpBook(){
println "out dumpBook"
}
三、DSL
1. 概念:
Domain Specific Language 领域特定语言
2. 特点:
- 在于专而不在于全
- 领域专家通过描述领域中的所有活动和规则,制定出某个特定领域的 DSL,这样就可以方便普通程序员在不是特别了解该领域原理的情况下,还能实现相关功能
3. Gradle
Gradle 就是一门 DSL,基于 Groovy,专门用于解决自动化构建的问题。程序员即使不了解自动化构建的原理,按照 Gradle 的语法,编写相关的脚本代码,也可以完成项目的自动化构建
整理学习自飞雪无情大佬的《Android Gradle 权威指南》和互联网资料