學(xué)習(xí)Gradle诞吱,前前后后總結(jié)了一些內(nèi)容寻定,然后整理出了一個(gè)系列辖源,共計(jì)10篇文章蔚携,與大家分享:
- Groovy基本介紹
- 開始使用Gradle
- 自定義屬性
- 深入了解Task和構(gòu)建生命周期
- Gradle增量式構(gòu)建
- 掛接到構(gòu)建生命周期
- 編寫和使用自定義Task
- 依賴管理
- 多項(xiàng)目構(gòu)建
- 自定義Gradle插件
學(xué)習(xí)本系列前可以下載相關(guān)的github項(xiàng)目gradleLearnDemo。
地址:https://github.com/sososeen09/gradleLearnDemo
0 前言
Gradle腳本使用的是Groovy語(yǔ)言克饶,Groovy也是基于JVM的一種動(dòng)態(tài)語(yǔ)言酝蜒,基于Java并擴(kuò)展了Java語(yǔ)言。Groovy會(huì)使寫Java程序就要寫腳本一樣簡(jiǎn)單矾湃,寫完就可以執(zhí)行亡脑,所以看起來(lái)也像是一門腳本語(yǔ)言。Groovy內(nèi)部會(huì)把代碼編譯為Java class文件然后啟動(dòng)虛擬機(jī)來(lái)執(zhí)行,這些過程霉咨,我們開發(fā)人員是不用管的蛙紫。
Gradle是一種DSL,也即是 Domain Specific Language 領(lǐng)域特定語(yǔ)言躯护。說(shuō)白了DSL就是一種行話惊来,這個(gè)語(yǔ)言在Gradle中可以識(shí)別,在其它地方就用不了了棺滞。
學(xué)習(xí)Gradle裁蚁,我們不必要精通Groovy語(yǔ)言,但還是需要了解一些Groovy的基本知識(shí)继准,比如def關(guān)鍵字枉证、返回語(yǔ)句、字符串移必、集合室谚、閉包等。下面崔泵,我們就來(lái)簡(jiǎn)單介紹一下秒赤。
1 Groovy代碼的執(zhí)行
前面我們說(shuō)了,Groovy很像是一門腳本語(yǔ)言憎瘸,我們來(lái)看一下怎么回事入篮。
創(chuàng)建一個(gè)HelloGroovy.groovy文件,里面就一行代碼
println 'hello groovy!'
然后執(zhí)行命令groovy HelloGroovy.groovy
,得到結(jié)果
hello groovy!
是不是很簡(jiǎn)單幌甘,很像腳本語(yǔ)言潮售。
2 Groovy中的字符串
Groovy 對(duì)字符串支持相當(dāng)強(qiáng)大,可以使用多種字符串锅风,包括單引號(hào)酥诽、雙引號(hào)、三引號(hào)皱埠。
String str='hello groovy!'
String getStr(){
'hello groovy!'
}
String str1='hello'
String str2=' groovy!'
println 'hello groovy!'
println "hello groovy!"
println "$str"
println getStr()
println "${str1+str2}"
println 'hello $str2' //單引號(hào)肮帐,直接打印內(nèi)容
使用單引號(hào)會(huì)直接打印字符串的內(nèi)容,不會(huì)對(duì)美元$符號(hào)的內(nèi)容進(jìn)行轉(zhuǎn)義边器。使用雙引號(hào)的功能更加強(qiáng)大训枢,字符串中使用美元符$后面可以跟字符串變量,如"$str"
饰抒,也可以跟表達(dá)式如 "${str1+str2}"
,如果跟表達(dá)式诀黍,記得要用{}括起來(lái)袋坑。
三引號(hào)用的比較少,可以支持字符串內(nèi)容換行,我們了解一下就行枣宫。
println ''' aa
bb
cc
'''
我們?cè)趃etStr()方法中并沒有使用return語(yǔ)句婆誓,這是因?yàn)镚roovy默認(rèn)是把最后一行的執(zhí)行結(jié)果進(jìn)行返回。如果你需要返回的結(jié)果正好是最后一行也颤,就可以省略return洋幻。
另外,在Groovy中翅娶,語(yǔ)句的最后的“文留;”
號(hào)是可以省略的。還有一點(diǎn)就是Groovy中在調(diào)用函數(shù)的時(shí)候可以不加括號(hào)竭沫,比如燥翅,println ("hello")
與 println "hello"
的意思是一樣的
3 def關(guān)鍵字
def關(guān)鍵字很像是Java中的Object,在定義變量或者方法的時(shí)候使用def蜕提,如果沒有指定具體的參數(shù)類型森书。在運(yùn)行階段Groovy會(huì)自動(dòng)判斷參數(shù)類型。
def a = 1, b = 2
def str = "hello"
println a + b
println str
實(shí)際上我們?cè)诙x變量的時(shí)候是可以省略def的谎势,如
a = 1
b = 2
str = "hello"
但是凛膏,最好還是加上def,這是一種好的實(shí)踐脏榆。
你還可以在定義變量的時(shí)候猖毫,在def后面再加上具體的參數(shù)類型,如
def int a = 1
def String str = "hello"
使用def定義方法的返回值類型姐霍,可以返回任意類型鄙麦。如果指定了具體的返回值類型,就要正確的返回镊折,否則會(huì)報(bào)錯(cuò)胯府。
4 集合
Groovy的基本類型與Java一樣。對(duì)于集合類型的數(shù)據(jù)恨胚,List的具體實(shí)現(xiàn)是ArrayList骂因。Map集合的具體實(shí)現(xiàn)是LinkedHashMap。
4.1 List
下面我們來(lái)簡(jiǎn)單了解一下如果使用赃泡。List使用一個(gè) []中括號(hào)來(lái)括起來(lái)來(lái)表示的寒波。
//定義一個(gè)List
def lists=['groovy','gradle','android']
//打印集合size
println lists.size
//打印集合中的數(shù)據(jù)
lists.each{
list->println list
}
取出集合中的數(shù)據(jù)直接用索引就可以了。比如:
assert lists[0]=='groovy'
對(duì)于集合中變量的存儲(chǔ)升熊,我們是不需要擔(dān)心數(shù)組越界的俄烁,如果索引超過當(dāng)前長(zhǎng)度,List會(huì)自動(dòng)在該索引中添加元素级野。比如
lists[100]=100
println lists.size
println lists[99]
打印結(jié)果页屠,會(huì)發(fā)現(xiàn)集合的size變?yōu)?01。index為99的集合數(shù)據(jù)為null。
4.2 Map
Map的表示就是用中括號(hào)[]括起來(lái)的 key:value形式辰企。
def map=["key1":"hello","key2":"groovy","key3":true]
println map.size()
map.forEach{
key,value->
println "$key :$value"
}
結(jié)果是:
3
key1 :hello
key2 :groovy
key3 :true
獲取Map的元素
println map.'key1'
println map['key1']
添加元素
map.'key4'='android'
println map['key4']
5 Groovy的類
Groovy中的類與Java中的類的寫法類似风纠,但是要更簡(jiǎn)潔一些。
我們?cè)贖ello.groovy文件中寫一個(gè)HelloWorld類牢贸。
class HelloWorld{
String msg='hello world'
HelloWorld(){
}
HelloWorld(String msg){
this.msg=msg
}
void sayHello(){
println msg
}
}
def say={
new HelloWorld('hello').sayHello()
}
def getMsg={
new HelloWorld().msg
}
say()
println getMsg()
調(diào)用groovy Hello.groovy
命令執(zhí)行該腳本竹观,結(jié)果如下:
hello
hello world
當(dāng)然了,我們也可以寫一個(gè)單獨(dú)的HelloWorld類潜索,帶上包名臭增,然后在其它地方導(dǎo)包使用,就像Java那樣帮辟。有關(guān)于Groovy類的使用速址,我們后面還會(huì)講到,這里就不贅述了由驹。
總結(jié)一下Groovy的類相比Java的一些不同芍锚,或者說(shuō)是優(yōu)化的一些地方:
- 表達(dá)式后面的分號(hào)是可選的
- 每個(gè)類、構(gòu)造方法和方法默認(rèn)是public的
- 在Groovy中蔓榄,方法體中的最后一個(gè)表達(dá)式的值會(huì)被作為返回值并炮。這意味著return語(yǔ)句是可選的
- Groovy編譯器自動(dòng)加上getter/setter方法,所以不需要自己去書寫
- 類的屬性可以通過點(diǎn)號(hào)來(lái)獲取甥郑,看起來(lái)好像它們?cè)贘ava中是public的逃魄,在底層Groovy調(diào)用的是自動(dòng)生成的getter/setter方法。
6 閉包
閉包Closure澜搅,在Groovy中是很重要的一種數(shù)據(jù)類型伍俘。閉包實(shí)際上就是一段代碼塊,需要用{}包括起來(lái)勉躺。前面我們?cè)谥v解一些例子的時(shí)候已經(jīng)用到了閉包癌瘾,我們?cè)賮?lái)看一下閉包的結(jié)構(gòu)。
//定義一個(gè)閉包 饵溅,記得要用{}包裹起來(lái)
def aClosure={
int a,int b-> //-> 箭頭前面代表的是參數(shù)妨退,后面是執(zhí)行語(yǔ)句
a+b //返回值
}
println aClosure(1,2)
結(jié)果為 3。
閉包的參數(shù)類型也可以不指定蜕企,在運(yùn)行期有Groovy自動(dòng)推斷咬荷,比如下面這個(gè)例子,執(zhí)行起來(lái)也是沒有問題的
def bClosure={
a,b->
a+b
}
println bClosure(1,2)
閉包也可以沒有參數(shù)
如:
def aa={
println "this is a Closure"
}
aa()
總結(jié)一下轻掩,閉包的類型有
1. def closureNama ={params -> code}
2. def closureName= {code} 沒有參數(shù)的時(shí)候就沒有箭頭 ->
閉包的調(diào)用有兩種方式
1. 閉包對(duì)象.call(參數(shù))
2. 閉包對(duì)象(參數(shù))
如
aClosure(1,2)
aClosure.call(1,2)
需要注意一點(diǎn)幸乒,閉包如果沒有參數(shù)的話,其隱含了一個(gè)參數(shù)是 it
唇牧。
和this的作用類似罕扎,代表的是傳入閉包的參數(shù)基茵。比如:
def sayHello={"hello ${it}"}
println sayHello("Jim")
等同于
def sayHello={it->"hello ${it}"}
當(dāng)然了,如果閉包顯示的指明了無(wú)參數(shù)壳影,則在調(diào)用閉包的時(shí)候不能傳參數(shù),否則會(huì)報(bào)錯(cuò)弥臼。如
def noParams={->println "noParams"}
noParams();
//下面的代碼執(zhí)行會(huì)報(bào)錯(cuò)
//noParams(1)
閉包返回值
閉包總是會(huì)返回一個(gè)值宴咧。返回值是閉包的最后一條語(yǔ)句的值(如果沒有顯式的return語(yǔ)句),或者是可執(zhí)行的return 語(yǔ)句的值径缅。如果閉包的最后一條語(yǔ)句沒有值就返回null掺栅。如之前舉得Hello.groovy中的例子:
def getMsg={
new HelloWorld().msg
}
閉包作為方法參數(shù)
閉包也可以作為方法參數(shù),如:
int increment(Closure closure,int count){
closure()+count
}
//斷言纳猪,如果為true就正常執(zhí)行氧卧,如果為false,就會(huì)報(bào)錯(cuò)
assert increment({1+1},1)==3
閉包委托
閉包代碼是在委托的閉包上執(zhí)行氏堤。默認(rèn)的沙绝,這個(gè)委托就是閉包的所有者。比如你在Groovy腳本中定義了一個(gè)閉包鼠锈,那么所有者就是一個(gè)groovy.lang.Script實(shí)例闪檬。閉包的隱式變量delegate 允許你重新定義默認(rèn)的所有者。
例如:
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
assert y == 40
assert data == [x:10, y:30]
}
}
new Test().run()
上面例子中閉包c(diǎn)1的委托變?yōu)閐ata购笆,閉包的resolveStrategy在默認(rèn)情況下是OWNER_FIRST粗悯,即它會(huì)先查找閉包的owner(在本例中指的就是Test對(duì)象本身),如果owner存在同欠,則在owner上執(zhí)行閉包中的代碼样傍。這里我們將其設(shè)置成了DELEGATE_FIRST,即該閉包會(huì)首先查找delegate(本例中即data)铺遂,如果找不到再去找owner衫哥。resolveStrategy還有其它的一些情況,具體的可以查看文檔中的例子娃循,相信當(dāng)你看到這些例子后炕檩,會(huì)對(duì)閉包委托有一個(gè)清晰的認(rèn)識(shí)。
7 總結(jié)
限于篇幅和本系列的主題捌斧,本文簡(jiǎn)單介紹了Groovy的一些語(yǔ)法和數(shù)據(jù)結(jié)構(gòu)笛质,這對(duì)于學(xué)習(xí)Gradle會(huì)有一些幫助。在后面Gradle的學(xué)習(xí)過程中捞蚂,如果對(duì)Groovy的一些Api不熟悉可以查看Groovy的Api文檔妇押,我們沒必要死記硬背這個(gè)Api,掌握學(xué)習(xí)的方法更加重要姓迅,對(duì)嗎敲霍?
下一篇俊马,我們就正式進(jìn)入Gradle部分的學(xué)習(xí)了。