Gradle系列之Groovy基础
Gradle系列之Gradle基础
Gradle系列之自定义插件
Android构建流程(Android Plugin)源码解析系列一:主流程
数据类型
groovy中没有基本数据类型,它任务任何事物都是对象;它会将基本数据类型包装成其对应的包装类型
groovy中容器类
- List: 其底层对应java的List接口,一般用ArrayList作为实现类
- Map: 底层对应java的LinkedHashMap
- Range : Groovy对List的一种拓展
List
List的创建和修改
def emptyList = [] // 创建一个空的list
def list = ['hello', 100, 'word'] // List中可以存储多种数据类型
list[2] = 200 // 修改
list << 'fuck' // 新增
println list[2]
println list.size()
List的遍历
for (def i=0; i< list.size(); i++){
println list[i]
}
// each 遍历 list
list.each {
println it
}
// for in 遍历
for (v in list){
println v
}
Map
注意: key必须用字符串,如果使用的变量名,那么会将其识别为字符串(当前变量名的字符串,即使这个变量可以获取)
map的操作
def emptyMap = [:] // 创建空的map
def map = ['key1': 100, 'key2':'hello']
// 通过key获取value
def val1 = map.key1
def val2 = map['key2']
// 添加新元素
map['key'] = true
map的遍历
map.each {key, val ->
println 'map each : key : '+key+"; value : ${val}"
}
map.each {
println "map each(no params) : key: ${it.key}, value : ${it.value}" // 注意: ${}只能在 双引号中才能使用
}
Range
def range1 = 1..5 // 包含了 1,2,3,4,5
def range2 = 1..<5 // 包含 1,2,3,4(不包括5)
println range1.from
println range1.to
range1.each {
println "Range iterator : ${it}"
}
groovy的特性
- 会为对象的成员变量,自动增加getter和setter;所以我们查看api的时候,往往都会查到其成员变量对应get和set方法,我们 对象.成员变量,就是调用它的getter方法
- 默认访问权限是public
闭包
groovy里面的闭包,其实就是将一个方法作为一个参数传入到一个方法里面;它实现的功能和java中的回调函数类似。
我们先看闭包的一个,简单的例子
class Person {
String name
int age
def printPerson() {
println "name is ${name}, age is ${age}"
}
}
def person(Closure<Person> closure) {
Person p = new Person()
// 定义闭包中 执行对象
println closure.getResolveStrategy() // 默认 OWNER_FIRST
closure.delegate = p // 设置委托对象
closure.setResolveStrategy(Closure.DELEGATE_FIRST) // 修改委托策略
closure() // 执行委托
}
def printPerson() {
println '当前构建上下文 print person'
}
task configClosure << {
println 'execute config closure'
person {
// 因为上面的方法中,将委托策略改成了 DELEGATE_FIRST,也就是将作用域设置成了委托对象,也就是Person的对象
name = 'xiaoming'
age = 20
printPerson() // 这里执行的是Person对象的方法
}
}
关于闭包的重点,就是传入到方法中的闭包的作用域,不同的作用域,闭包中的代码执行不同的逻辑;关于闭包的策略,groovy提供了几种策略。
- OWNER_FIRST : 默认,当前对象优先,当前方法所在对象的作用域
- DELEGATE_FIRST: 委托对象优先;如果当前有委托对象,那么优先使用委托对象作为当前闭包的作用域范围;如果没有,那么使用当前方法的作用域对象。
- OWNER_ONLY : 只从当前方法对象的作用域内执行,如果没有找到对应的成员,直接抛出异常
- DELEGATE_ONLY: 只从委托对象的作用域内执行,如果没有知道对应的成员,直接抛出异常
- TO_SELF : 闭包会被编译成java中的类,此种情况会从当前闭包所在类的作用域内寻找对应的成员,如果没有,直接抛出异常
下面例子均来自官方文档
OWNER_FIRST
class Test {
def x = 30
def y = 40
def run() {
// 默认 OWNER_FIRST
def data = [x: 10, y: 20]
// 默认 owner_first : 设置委托对象无用
def cl = {
y = x + y
}
cl.delegate = data
cl()
println x == 30 // true
println y == 70 // true
println data == [x: 10, y: 20] // true
}
}
DELEGATE_FIRST
class Test {
def x = 30
def y = 40
def run() {
def data = [ x: 10, y: 20 ]
def cl = { y = x + y }
cl.delegate = data
cl.resolveStrategy = Closure.DELEGATE_FIRST
cl()
assert x == 30 // true
assert y == 40 // true
assert data == [x:10, y:30] // true
}
}
OWNER_ONLY
class Test {
def x = 30
def y = 40
def run() {
// OWNER_ONLY : 这种模式就是,即使你设置了delegate也没有用, 如果当前OWNER没有那么就会报错;并不会去delegate里面去寻找
// 下面案例: 如果Test没有 z, 就会报错
def data = [ x: 10, y: 20, z: 30 ]
def cl = { y = x + y + z } // 这里抛出异常
cl.delegate = data
cl.resolveStrategy = Closure.OWNER_ONLY
cl()
println x
println y
println data
}
}
注意: 如果上面的case,改成OWNER_FIRST,就不会抛出异常,并且只有在OWNER范围内没有找到的z,才会从委托对象去查找。输出结果如下:
30
100
[ x: 10, y: 20, z: 30 ]
DELEGATE_ONLY
这种策略就是只会从委托对象范围内寻找,如果没有找到,抛出异常,这里就不放例子了。
TO_SELF
class Test {
def x = 30
def y = 40
def run() {
def data = [ x: 10, y: 20, z: 30 ]
def cl = { y = x + y } // 抛出异常,因为当前闭包对象里面, x和y都没有
cl.delegate = data
cl.resolveStrategy = Closure.TO_SELF
cl()
println x
println y
println data
}
}
闭包的一个特性
如果一个方法的最后一个参数是一个闭包,那么调用这个方法的时候,可以将闭包放在外面。例子如下
def demo(int a, Closure closure){}
demo(2){
// 闭包代码
}
//上面等价于
demo(2, {
// 闭包代码
})
文件操作
def file = new File('app/a.txt') // 当前目录是 当前项目的根目录
// 逐行读取
file.eachLine {line, lineNo ->
println "${lineNo} ${line}"
}
// 一次性获取
byte[] bytes = file.getBytes()
// 以流的方式读取 (一次性获取);; 好处: 无需处理流的关闭操作
file.withInputStream {is ->
println is.getText()
}
def writeFile = new File('app/b.txt')
// write() 覆盖内容;; append() 向尾部追加内容
writeFile.withOutputStream { os ->
file.withInputStream { is ->
os << is // 重载了<< 符号,将输入流的数据传递给输出流
}
}
可以看出groovy对io的操作简化的很舒适。
特殊符号
groovy的特殊服务,能够简化我们很多代码。
def list = ['h', 'hello', 'jjj']
println list?.size() // ?. 相当于 判断list不为null,才执行size()方法, 否则直接返回null
println list*.size() // *. 相当于 用在集合对象里面,对里面每一个元素执行 size()方法,然后将返回值组成新的 list 返回
// .& 相当于 将一个对象的 方法 转变成 closure 然后传递
list.each(this.&printItem)
// .@ 相当于 直接获取一个 对象中的 变量;; 注意 .变量名 调用的是此变量的 gettter方法
def person = new Person(name : '小明')
println person.name // 调用name的 getter方法
println person.@name
// ?: 相当于 java中三目运算符, 但是判断条件是前面的内容
println person.@age ?: 'age is null'
as操作符
as操作符相当于java中的强制类型转换,它也支持数组和List之间的转换。
当然,groovy,可以直接赋值,不使用as操作符也可以。
String[] strs = ['a', 'b']
List list = strs as List
List list2 = strs