<<Android Gradle权威指南》阅读笔记——Groovy基础
本文讲述
Groovy 基础
,Groovy
是基于JVM虚拟机的一种动态语言,又在此基础上增加了很多动态类型和灵活特性,比如支持闭包,支持DSL
,可以说它是一门非常灵活的动态脚本语言。 每个
Gradle
的build脚本文件
都是Groovy脚本文件
你可以在里面写任何符合Groovy
语法的代码,比如定义类,声明函数,定义变量等;而Groovy
又完全兼容Java
,这就意味着你可以在build脚本文件
里写任何的Java代码。
1. 字符串
在
Groovy
中,单引号和双引号都可以定义一个字符串常量(Java
里单引号定义一个字符),不同的是单引号标记的是纯粹的字符串常量,而不是对字符串里表达式做运算,单引号没有运算能力,双引号可以:
- 类型:
task printStringClass << {
def str1 = '单引号'
def str2 = "双引号"
println "单引号定义的字符串类型:"+str1.getClass().name
println "双引号定义的字符串类型:"+str2.getClass().name
}
./gradlew printStringClass 输出
Task :printStringClass
单引号定义的字符串类型:java.lang.String
双引号定义的字符串类型:java.lang.String</pre>
- 运算
task printStringVar << {
def name = "张三"
println '单引号的变量计算:${name}'
println "双引号的变量计算:${name}"
}</pre>
./gradlew printStringVar 输出
Task :printStringVar
单引号的变量计算:${name}
双引号的变量计算:张三
2. 集合
Groovy
完全兼容了Java
的集合,并进行了扩展,使操作变得更容易。
-
List
在
Grroovy
中实现List
非常简单,同时还提供了下标索引、负下标、范围索引、迭代操作(each)
task printList << {
def numList = [1,2,3,4,5,6];
println numList.getClass().name //输出时可以看出 numList 是一个 ArrayList
println numList[1]//访问第二个元素 下标索引 下标从 0 开始
println numList[-1]//访问最后一个元素 负下标
println numList[-2]//访问倒数第二个元素 负下标
println numList[1..3]//访问第二个到第四个元素 范围索引 由”.."分开
numList.each{//迭代操作
println it //it 正在迭代的元素,这里涉及闭包的知识,下文会讲解
}
}
./gradlew printList 输出
Task :printList
java.util.ArrayList
2
6
5
[2, 3, 4]
1
2
3
4
5
6
-
Map
Map
的用法和
List类似,区别在于它的值是
K:V`键值对
task printMap << {
def mapl = ['width':1920,'height':1080]
println mapl.getClass().name //输出可以看出mapl是一个LinkedHashMap
//访问可以采用map[key]或者map.key两种方式
println mapl['width']
println mapl.height
mapl.each{//迭代操作
println "Key:${it.key},Value:${it.value}"//此处的it是一个Map.Entry实例
}
}
./gradlew printMap 输出
Task :printMap
java.util.LinkedHashMap
1920
1080
Key:width,Value:1920
Key:height,Value:1080
关于集合的更多方法后续会补充,有兴趣的可以自行先了解
3. 方法
通过了解
Groovy
方法和Java
方法的不同,更利于我们明白Gradle
脚本里的代码
-
括号可以省略
Groovy
调用一个方法比Java
灵活的多,可以省略(),在定义DSL时非常有用并且书写方便
task invokeMethod << {
//这两种调用方式结果一直,但第二种更简洁
methodl (1,2)
methodl 1,2
}
def methodl(int a, int b){
println a+b
}
./gradlew invokeMethod 输出
Task :invokeMethod
3
3
-
return 可以不写
Groovy
在没有return
时,会将方法执行过程中的最后一句作为返回值
task printMethodReturn << {
def add1 = method2 1,2
def add2 = method2 5,3
println "add1:${add1},add2:${add2}"
}
def method2(int a,int b){
if(a>b){
a //执行到此处 返回a
}else{
b //执行到此处 返回b
}
}
./gradlew printMethodReturn 输出
Task :printMethodReturn
add1:2,add2:5
-
代码块可以作为参数传递
通过
each
方法,我们可以直接的理解这个问题
//最初的写法
numList.each({println it})
//经过格式化
numList.each({
println it
})
//Groovy中方法的最后一个参数为闭包,可以放到外面
numList.each(){
println it
}
//去掉方法的括号
numList.each{
println it
}
4. JavaBean
JavaBean
中繁琐的getter/setter
在Groovy
中得到了很大改善
task helloJavaBean << {
Person p = new Person()
println "名字是:${p.name}"//此时name为赋值,返回null
p.name = 'tom'
println "名字是:${p.name}"//已赋值,返回tom
println "年龄是:${p.age}"//未定义成员变量时,通过getAge()方法也可获取age,但不能修改值
}
class Person{
private String name
public int getAge(){
12
}
}
./gradlew helloJavaBean 输出
Task :helloJavaBean
名字是:null
名字是:tom
年龄是:12
5. 闭包
闭包是
Groovy
的一个非常重要的特性,可以说他是DSL的基础。
task helloClosure << {
//使用自定义闭包
customEach {
println it
}
//多个参数
eachMap {k,v ->
println "${k} is ${v}"
}
}
def customEach(closure){//唯一参数,用于接收一个闭包(代码块)
//模拟一个集合,开始迭代
def numList = [1,2,3]
numList.each{
closure(it)
}
}
def eachMap(closure){//此处的闭包传递两个参数k v
def mapl = ["name":"tom","age":18]
mapl.each{
closure(it.key,it.value)
}
}
./gradlew helloClosure 输出
Task :helloClosure
1
2
3
name is tom
age is 18
- 闭包委托
Groovy
闭包的强大之处在于它支持闭包方法的委托。Groovy
的闭包有thisObject
,owner
,delegate
三个属性,当你在闭包内调用方法时,由它们来确定使用哪个对象来处理。默认情况下delegate
和owner
是相等的,但是delegate
是可以被修改的,这个功能是非常强大的,Gradle
中的很多功能都是通过修改delegate
实现的。
task helloDelegate << {
new Delegate().test{
println "thisObject:${thisObject.getClass()}" //thisObject优先级最高
println "owner:${owner.getClass()}"//owner优先级次之
println "delegate:${delegate.getClass()}"
//delegate优先级最低,但是owner==delegate
//闭包内方法的执行顺序:thisObject>owner>delegate
method3()
it.method3()
}
}
def method3(){
println "Context this:${this.getClass()} in root"
println "method3 in Delegate"
}
class Delegate{
def method3(){
println "Delegate this:${this.getClass()} in Delegate"
println "method3 in Delegate"
}
def test(Closure<Delegate> closure){
closure(this)
}
}
./gradlew helloDelegate 输出
Task :helloDelegate
thisObject:class build_edqlj0scrowqqm8jgfgirxcz4
owner:class build_edqlj0scrowqqm8jgfgirxcz4$_run_closure10
delegate:class build_edqlj0scrowqqm8jgfgirxcz4$_run_closure10
Context this:class build_edqlj0scrowqqm8jgfgirxcz4 in root
method3 in Delegate
Delegate this:class Delegate in Delegate
method3 in Delegate
在
DSL
中,比如Gradle
,我们会指定delegate
为当前的it
,这样我们在闭包内就可以对该it
进行配置,或调用其方法。
task configClosures << {
man {//在闭包类直接对Man实例配置
manName = "tom"
manAge = 19
dumpMan()
}
}
class Man{
String manName
int manAge
def dumpMan(){
println "name is ${manName},age is ${manAge}"
}
}
def man(Closure<Person> closure){
Man p = new Man();
//设置委托对象为当前创建的Man实例
closure.delegate = p
//委托模式优先
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
closure(p)
}
./gradlew configClosures 输出
Task :configClosures
name is tom,age is 19
6. DSL
DSL
(Domain Specific Language)——领域特定语言(专门关注某一领域的语言)
Gradle
就是一门DSL
,它基于Groovy
专门解决自动化构建的DSL
。
到这
Groovy基础
就简单介绍完了,后续我们再学习新的Gradle
知识,欢迎持续关注