Gradle(1)- Groovy基础

送给自己的花儿

Gradle是目前Android主流的构建工具,不管你是通过命令行还是通过Android Studio来build,最终都是通过Gradle来实现的,所以学习Gradle非常重要。

Groovy最终被编译成class字节码文件运行在jvm上,所以Java的特性Groovy都支持,但是Groovy提供了一些更加简洁的语法,比如利用闭包特性来进行文件IO,解析XML,简直让你难以置信。

一.开发环境准备

  • 方式一:安装Groovy SDK,安装方法参考 http://www.groovy-lang.org/download.html,下载后解压即可,最好是设置一下环境变量。
  • 方式二:直接在Android Studio中开发,创建一个普通的Android Project,在build.gradle文件中编写一个task来执行,示例:
task(jdqm).doLast {
    println "Start execute hello."
    hello()
}

def hello() {
    println "Hello jdqm."
    //todo add your code here
}

在hello方法中编写你的Groovy代码,然后通过如下命令来执行

gradlew jdqm

作为Android开发者,个人比较推荐是用第二种方式,毕竟我们的目标是Gradle。

二. 开发实战

Groovy中的注释与Java中的一样,单行注释//,多行注释/**/

1.def关键字定义变量

def int aInt = 1;
def String aString = "I am a String.";
  • 分号不是必须的
  • def关键字可省略
  • 数据类型自动推断

上面的代码可以写成这样

aInt = 1
aString = "I am a String."
bInt = 2

2.方法的参数类型和返回值类型可省略

def getSomeThing(param1) {
    return param1
}
println getSomeThing("Hello Jdqm.")

请注意 println getSomeThing("Hello Jdqm.") 这一行,实际是调用了 println(String)这个方法,但你会发现没有圆括号,所以方法调用圆括号也不是是必须的,前提是不引起混淆。下面这两种写法效果是一样的:

println getSomeThing("Hello Jdqm.")
println(getSomeThing("Hello Jdqm."))

那什么时候会混淆,比如

//方法调用省略圆括号,容易引起混淆,getSomeThing 会被当成属性
println getSomeThing "Hello Jdqm."

3.return关键字可省略

//return关键字可省略,返回值为最后一条语句的执行结果
def getSomeThings(param1, param2) {
    param1 + param2
}

result = getSomeThings 3, 4
println result // 7

注意:方法的返回值类型和def关键字不能同时省略,否则会报找不到方法。

4.字符串

//单引号为严格意义的字符串,输出 I am $ dollar
String singleQuote(){
    return 'I am $ dollar'
}
println singleQuote() // I am $ dollar
//双引号不是严格的字符串,如果其中有$表达式,会先对表达式求值
String doubleQuote(){
    def x = 1
    "I am $x dollar" 
}
println doubleQuote()  // I am 1 dollar
//三引号可以随意换行
String threeQuote(){
    '''line1
    line2
    line3'''
}  

5.自动类型推断

//自动推断类型
def x = 1
println x.getClass().getCanonicalName() //java.lang.Integer

6.加强版 List

List可以存放任何类型的数据类型

List emptyList = []  // 通过[]来创建List
List testList=[100, 'hello', true]
println(testList[0])  //100
println(testList[1])  //hello
println(testList[2])  // true
assert testList[0]==100  //true
assert testList[100]==null / /true
//不会有下标越界异常,自动扩展List的大小
testList[100]=10
println testList[100]  //10
println testList.size()  //101,注意这个List的大小已经变为101,那么中间的元素默认值是什么是什么?是null

是不是特别像Java中的List<Object>

7.Map

通过[:]来创建,key默认是String,可以不加引号,但是容易引起混淆,单引号双引号都可以。

Map emptyMap = [:]
Map testMap = ['key1':'value1','key2':'value2']
println(testMap.key1)  //value1
println(testMap['key2']) //传统的取值方式
testMap.anotherkey='anothervalue' //添加一个元素
println testMap.anotherkey  //anothervalue

8.Range

def aRange=1..5    //1 2 3 4 5
def bRange=1..<5    //1 2 3 4
println aRange.from    //1
println aRange.to    //5
println bRange.from    //1
println bRange.to    //4

其中 aRange.from这种调用方式,实际上是调用了aRange.getFrom()方法。

9.闭包

闭包是一个比较重要的内容。

def aClosure = {String param1, String param2->
    println param1
    println param2
}

//有两种调用方式
aClosure.call('hello', 'groovy')
aClosure('hello','groovy')

定义无参数closure,不代表不能传参数

def bClosure={
   println 'hello world of groovy.'
   println it  // 没有定义参数的时候,有一个隐含参数it
}
bClosure.call()    //不传参数调用,it为null
bClosure(100)    //it为100

下面这种写法表示闭包没有参数,调用时不能传入参数,否则会报错

def cClosure={->
    println 'hello world.'
}

//不传入参数调用,正确
cClosure.call()

//这样调用会报错
//cClosure.call('test')

方法的最后一个参数是闭包,可以将这个闭包参数写到圆括号外

def testClosure(int a, String param, Closure closure){
    println ("$a,$param")
    closure.call()
}

//传统的调用方式
testClosure(10, 'groovy',{
    println('I am a Closure')
})

//最后一个参数写到圆括号外
testClosure(10, 'groovy') {
   println('I am a Closure')
}

10. 文件IO

首先回顾一下在Java中进行文件IO,假设存在这样的test.txt

hello
groovy
I
am 
Jdqm.

现在需要通过Java IO读这个文件的内容并输出到控制台

BufferedReader bufferedReader = null;
try {
    File file = new File("test.txt");

    //文本内容可以使用字符流
    FileReader fileReader = new FileReader(file);
    
    //将字符流包装为BufferReader,方便按行读取
    bufferedReader = new BufferedReader(fileReader);
    String line;
    while ((line = bufferedReader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (bufferedReader != null) {
        try {
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

即便使用Java7中的自动关闭流来省略掉finally块,代码仍然比较繁琐。接下来使用Groovy来完成同样的功能。

File file = new File('test.txt')
file.eachLine {online->
    println online
}

到这里我只想到两个词:简洁、明了。这里使用到了闭包,而闭包的难点是如何确定参数,最好的方式是查官方文档。http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/File.html#eachLine(groovy.lang.Closure)

API文档

从文档说明中我们得知调用时闭包可以是1个或者2个参数, 第一个参数是当前行的内容,第二个参数(可选)是当前的行号(从1开始)。所以我们可以这样

File file = new File('test.txt')
file.eachLine{line, lineNum ->
    println lineNum + " " + line
}

//输出结果
1 hello
2 groovy
3 I
4 am
5 Jdqm.

下面将test.txt的内容写入test1.txt

File sourceFile = new File('test.txt')
File targetFile = new File('test1.txt')
targetFile.withOutputStream{os->
    sourceFile.withInputStream{is->
        os<<is
    }
}

11. 解析XML

Groovy访问xml有两个类:XmlParser和XmlSlurper,二者几乎一样,在性能上有细微的差别,参考链接 http://docs.groovy-lang.org/docs/latest/html/api/

    def xml = '<root><one a1="uno!"/><two>Some text!</two></root>'
    def rootNode = new XmlParser().parseText(xml)
    assert rootNode.name() == 'root'
    assert rootNode.one[0].@a1 == 'uno!'
    assert rootNode.two.text() == 'Some text!'
    rootNode.children().each { assert it.name() in ['one','two'] }

12.其他

在Groovy中,Getter/Setter和属性是默认关联的,比如:

class Book {
   private String name
   String getName() { return name }
   void setName(String name) { this.name = name }
}

class Book {
   String name
}

上述两个类完全一致,只有有属性就有Getter/Setter;同理,只要有Getter/Setter,那么它就有隐含属性。

with操作符
在Groovy中,当对同一个对象进行操作时,可以使用with,比如:

Book bk = new Book()
bk.id = 1
bk.name = "android art"
bk.press = "china press"

可以简写为:

Book bk = new Book() 
bk.with {
   id = 1
   name = "android art"
   press = "china press"
}

判断是否为真
在Groovy中,判断是否为真可以更简洁:

if (name != null && name.length > 0) {}

可以替换为:

if (name) {}

简洁的三元表达式
在Groovy中,三元表达式可以更加简洁,比如:

def result = name != null ? name : "Unknown"

// 省略了name
def result = name ?: "Unknown"

简洁的非空判断
在Groovy中,非空判断可以用?表达式,比如:

if (order != null) {
   if (order.getCustomer() != null) {
       if (order.getCustomer().getAddress() != null) {
       System.out.println(order.getCustomer().getAddress());
       }
   }
}

可以简写为:

println order?.customer?.address

使用断言
在Groovy中,可以使用assert来设置断言,当断言的条件为false时,程序将会抛出异常:

def check(String name) {
   // name non-null and non-empty according to Gro    ovy Truth
   assert name
   // safe navigation + Groovy Truth to check
   assert name?.size() > 3
}

switch方法
在Groovy中,switch方法变得更加灵活,可以同时支持更多的参数类型:

def x = 1.23
def result = ""
switch (x) {
   case "foo": result = "found foo"
   // lets fall through
   case "bar": result += "bar"
   case [4, 5, 6, 'inList']: result = "list"
   break
   case 12..30: result = "range"
   break
   case Integer: result = "integer"
   break
   case Number: result = "number"
   break
   case { it > 3 }: result = "number > 3"
   break
   default: result = "default"
}
assert result == "number"

==和equals
在Groovy中,==相当于Java的equals,,如果需要比较对个对象是否是同一个,需要使用.is()。

Object a = new Object()
Object b = a.clone()

assert a == b
assert !a.is(b)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容