前言
Groovy是JVM語言,與Java語法類似祟辟,如果你熟悉kotlin的話闸度,你會發(fā)現(xiàn)它與kotlin更類似些此再。它可以作為Java平臺的腳本語言使用君仆。詳細(xì)介紹請見Groovy官網(wǎng)和維基百科。
提示:“Groovy基礎(chǔ)”這一部分建議不要花費太多時間娶视,能看懂語法隘蝎,尤其是閉包的語法,以及知道如何查閱API即可襟企。
語法
對于語法的學(xué)習(xí)嘱么,我這里就不詳細(xì)說了,請大家按照下面步驟去學(xué)習(xí):
- 瀏覽一遍官方文檔的語言規(guī)范顽悼,里面有示例曼振,很容易看懂。要知道Groovy語言規(guī)范大致講了哪些內(nèi)容蔚龙,以后遇到不懂的語法冰评,可以回來快速查閱。
- 另外木羹,也可以看下國人寫的入門博客:任玉剛 Gradle從入門到實戰(zhàn) - Groovy基礎(chǔ)甲雅、使用Groovy開發(fā)之新特性解孙。
重點看的部分
- 閉包Closures。定義抛人、使用弛姜、代理策略(
owner
,delegate
andthis
) - 語義Semantics。重點看
Promotion and coercion
妖枚、Optionality
和Typing
部分廷臼,尤其是和閉包相關(guān)的部分。
API文檔使用說明
Groovy API包括兩部分绝页,一部分是Groovy化的JDK API(groovy-jdk
)荠商,另一部分是新增的純Groovy API(gapi
)。
文檔入口:
-
官網(wǎng)Document->API documentation
- 直接進入API文檔
Groovy化的JDK API
This document describes the methods added to the JDK to make it more groovy.
Groovy在JDK中增加了許多方法续誉,如在List
增加了public List each(Closure closure)
莱没、public List dropWhile(Closure condition)
等方法,使其Groovy化屈芜。
查找API示例:查看List
中public List each(Closure closure)
方法詳情郊愧。
通過包(
Package
)查。java.util
->Interfaces
->List
->each(Closure closure)
通過索引(
Index
)查井佑。Index
-> 頁面搜索each(groovy.lang.Closure)
(Mac
版Chrome
瀏覽器快捷鍵Command+F
) -> 找到Method in interface java.util.List
一項
最終結(jié)果如下:
描述說是迭代一個
List
属铁,并將每個子項作為參數(shù)傳遞到閉包中進行處理。
新增的Groovy類 API
Groovy - An agile dynamic language for the Java Platform
(GroovyDoc for Groovy and Java classes)
上面說的是Groovy and Java classes
文檔躬翁,包括Groovy
類和原生Java
類(可通過文檔中的類的鏈接查看)焦蘑。尤其要注意,這個文檔中的JDK API
點擊后都會鏈接到原始的Java類盒发,而不是Groovy化的Java類例嘱。
查看某個API詳情的方法與上面的相同,略宁舰。
示例-Map語法
創(chuàng)建Gradle項目拼卵,并添加名為groovySyntax的任務(wù)
$ mkdir groovy-syntax
$ cd groovy-syntax
$ vi build.gradle
build.gradle
文件
task(groovySyntax).doLast {
println 'start groovy syntax task'
doMap()
}
def doMap() {
def emptyMap = [:]
def test = ["id":1, "name":"zhangliang", "isMale":true]
test["id"] = 2
test.id = 900
println test.id
println test.isMale
println test
test.each { key ,value ->
println "key=$key, value=$value"
}
test.each { entry ->
println "entry->$entry,${entry.key}, ${entry.value}"
}
}
執(zhí)行gradle groovySyntax
,輸出如下
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :groovySyntax
start groovy syntax task
900
true
{id=900, name=zhangliang, isMale=true}
key=id, value=900
key=name, value=zhangliang
key=isMale, value=true
entry->id=900,id, 900
entry->name=zhangliang,name, zhangliang
entry->isMale=true,isMale, true
BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed
上面的代碼和輸出結(jié)果不難理解蛮艰,分析如下:
- 方法沒有嵌套時腋腮,括號可以省略。
println 'start groovy syntax task'
和test.each{...}
寫全就是println('start groovy syntax task)'
和test.each({...})
-
Map
的定義參見語言規(guī)范-Map壤蚜。 -
Map
的方法each(Closure closure)
的API文檔說明如下
Allows a Map to be iterated through using a closure. If the closure takes one parameter then it will be passed the Map.Entry otherwise if the closure takes two parameters then it will be passed the key and the value.
可以用一個閉包來迭代Map
即寡,閉包的參數(shù)如果是一個就作為Map.Entry
,如果兩個參數(shù)就作為key
和value
袜刷。
示例-修改Android項目輸出的APK名稱
Android開發(fā)中聪富,打包完后修改apk的名稱是一個比較常見的做法。之前開發(fā)的Android項目中著蟹,在app/build.gradle
中加入了幾行代碼墩蔓,每次打包后自動修改apk的名稱梢莽,相關(guān)代碼如下:
app/build.gradle
...
// 利用git commit count 作為構(gòu)建號
static def gitBuildCode() {
def cmd = 'git rev-list HEAD --first-parent --count'
cmd.execute().text.trim().toInteger()
}
static def appName() {
return "youchat"
}
// 修改輸出文件的名稱
android.applicationVariants.all { variant ->
variant.outputs.all {
if (outputFileName != null && outputFileName.endsWith('.apk')) {
def endStr = outputFileName
if (outputFileName.contains("debug")) {
endStr = "debug.apk"
} else if (outputFileName.contains("preRelease")) {
endStr = "preRelease.apk"
} else if (outputFileName.contains("release")) {
endStr = "release.apk"
}
outputFileName = "${appName()}_${android.defaultConfig.versionName}_${gitBuildCode()}_${endStr}"
}
}
}
...
打包完后,可以得到類似下面的文件
app/build/outputs/apk/preRelease/youchat_7.5.0_999_preRelease.apk
上面的代碼邏輯比較簡單钢拧,簡單分析如下:
- 定義了兩個方法蟹漓。
gitBuildCode ()
方法沒有寫return
關(guān)鍵字,因為在Groovy
中源内,方法總會返回值的葡粒,如果沒有寫return
,就返回最后一行產(chǎn)生的值膜钓。參見語言規(guī)范-Object orientation-Method
Methods in Groovy always return some value. If no return statement is provided, the value evaluated in the last line executed will be returned
-
android.applicationVariants.all(Closure var1)
和variant.outputs.all(Closure var1)
是Gradle DSL語法嗽交,可以查看它的javadoc
Executes the given closure against all objects in this collection, and any objects subsequently added to this collection. The object is passed to the closure as the closure delegate. Alternatively, it is also passed as a parameter.
迭代容器中所有的對象,并傳遞給閉包進行處理颂斜。
-
variant.outputs.all(Closure var1)
閉包中的代碼邏輯是很簡單的夫壁,只說下最后一行outputFileName
的賦值語句,它使用了字符串插值語法${}
沃疮,與kotlin里字符串模板是類似的盒让。