gradle使用的groovy基础知识
Gradle使用的是groovy语言,所以要先掌握groovy的基础知识,groovy几乎100%兼容java,所以学习起来还是很轻松的
本文在介绍时以代码为主,简化了很多文字描述,介绍了gradle用户所需要了解的groovy知识,运行时可以将代码放到项目中使用的build.gradle文件中,然后编译gradle文件,android studio位置如下所示:
变量和函数
Groovy中支持动态类型,即定义变量的时候可以不指定其类型。Groovy中,变量定义可以使用关键字def。注意,虽然def不是必须的,但是为了代码清晰,建议还是使用def关键字
def variable1 = 1 //可以不使用分号结尾
def varable2 = "I am a person"
def int x = 1 //变量定义时,也可以直接指定类型
函数定义时,参数的类型也可以不指定。比如
String testFunction(arg1,arg2){ //无需指定参数类型
...
}
函数都有返回值
//如果函数无返回类型,必须使用def关键字
def nonReturnTypeFunc(){
last_line //最后一行代码的执行结果就是本函数的返回值
}
//如果指定了函数返回类型,则可不必加def关键字来定义函数
String getString(){
return "I am a string"
}
assert语句
groovy的assert语句一直有用
def version = 12
assert version == 12 //成功
version++
assert version == 12 //失败
可选的括号
下面两句是等价的
println('hello world')
println 'hello world'
字符串(GString)
三种形式:
单引号包裹:
与java的双引号包裹等价
'hello world'
双引号包裹:
可以方便的放入变量
def language = 'groovy'
def sentence = '$language is awesome'
assert sentence == 'groovy is awesome' //success
//如果使用了表达式,可以使用大括号括起来
def improvedSentence = "${language.toString()} is awesome"
assert improveSentence == 'groovy is awesome'
三个双引号包裹:
方便的长文本
def string3 = """
This
is a
multiline
string
"""
集合
List
def buildTools = ['Ant','Maven'] //方便的定义list
assert buildTools.getClass() == ArrayList //底层是java.util.ArrayList
assert buildTools[1] = 'Maven' //像数组一样方便调用
buildTools << 'Gradle' //在底层调用了add方法
assert buildTools[2] == 'Gradle'
//each函数接收的是闭包当做参数,详情见本文的闭包部分
//buildTool是参数,既是list中具体的值
buildTools.each{ buildTool ->
println buildTool //遍历list中的值
}
Map
def inceptionYears = ['Ant': 2000, 'Maven': 2004] //方便的定义map
assert inceptionYears.getClass() == LinkedHashMap //默认实现是java.lang.LinkedHashMap
assert inceptionYears.size() == 2
assert inceptionYears.Ant == 2000
assert inceptionYears['Ant'] == 2000 //两种取值或赋值方式
inceptionYears.Gradle = 2009 //如果键值不存在,直接添加一组新值
assert inceptionYears.Gradle == 2009
inceptionYears.each {buildTool,year ->
//遍历map
println "$buildTool was first realeased in $year"
}
闭包
闭包是一个类型为groovy.lang.Closure的代码块,与其他语言的lambdas表达式相似。闭包可以被赋值给变量,作为参数传递给方法,并像普通方法一样来调用。
闭包就像java中的函数,有参数,执行体,返回值,不过它的用法和变量类似,它的值需要用大括号“{}”包裹起来
闭包的参数和返回值
//隐式的闭包参数
def myClosure1 = {
//没有显式定义参数,则默认有一个隐式参数it
println "隐式参数:$it"
}
myClosure1("ldy")
//显式的闭包参数
def myClosure2 = {
//lambdas,“->”左侧为参数,右侧为执行体(和函数类似)
String name,String phoneNumber ->
println("name:$name,phoneNumber:$phoneNumber")
}
myClosure2("ldy","123456")
def myClosure3 = {
//参数可以不指定类型
name,phoneNumber ->
println("name:$name,phoneNumber:$phoneNumber")
name //闭包总会返回最后一条语句的值(相当于函数返回值)
}
assert myClosure3("ldy","123456") == 'ldy' //闭包的返回值
闭包作为方法参数
//定义一个方法,参数是一个闭包
def testClosure(Closure closure) {
//调用闭包并传递参数
closure("ldy", "123456")
}
//调用方法,省略圆括号,传递闭包作为参数
testClosure {
name, phoneNumber ->
println("name:$name,phoneNumber:$phoneNumber")
name
}
//调用方法,将上个例子的闭包作为参数
testClosure(myClosure3)
闭包委托
闭包代码在委托的闭包上执行,默认的,这个委托就是闭包的所有者
因为闭包定义的地方(就是闭包代码真实的位置)和调用的地方可能不是一个地方,就像java类中的方法一样,可以调用同属于这个类的其它方法,但是却无法这样调用其它类中的方法,如果重设闭包的委托属性delegate
就相当于闭包的代码真实的放置到委托的对象中一样
//定义一个类
class Person{
//默认为public
Integer age
void increment(Closure closure){
//delegate是闭包的隐式变量,允许你重新定义闭包的所有者
//将闭包的所有者定义为this
closure.delegate = this
//调用闭包
closure()
}
}
//创建对象,可以直接这样传递参数
Person projectVersion = new Person(age: 20)
//因为重定义了委托,所以闭包可以在类外自由调用对象中的属性和方法,就像这段代码是放置到类中一样
projectVersion.increment {age += 1}
assert projectVersion.age == 21 //对象属性真实被改变了