最近在學(xué)習(xí) Android 中 Gradle 相關(guān)的知識(shí),如果想學(xué)好 Gradle,必要的 Groovy 基礎(chǔ)是不可少的。Groovy 語(yǔ)言的知識(shí)也是非常多的,如果只是想在 Android Gradle 這個(gè)范圍內(nèi)使用 Groovy,會(huì) Groovy 的基礎(chǔ)即可,Groovy 語(yǔ)言文檔。本篇文章主要介紹了 Groovy 中的變量、String、List、Map、類和對(duì)象、閉包等內(nèi)容,示例代碼都在 GradleForAndroid
一. Android Gradle 概述
Groovy 是從 Java 衍生出來(lái)的,Groovy 的源代碼文件 .groovy 也是編譯成為 .class 文件,然后運(yùn)行在 JVM 虛擬機(jī)上的。其目標(biāo)是,不管是作為腳本語(yǔ)言,還是編程語(yǔ)言,都可以簡(jiǎn)單、直接的使用。在 Android 的 Gradle 中,Groovy 更多的是用于編寫(xiě)腳本。如果會(huì) Java,學(xué)習(xí) Groovy 會(huì)比較簡(jiǎn)單,甚至可以混寫(xiě) Java 和 Groovy 語(yǔ)法。
Groovy 相比 Java 語(yǔ)言來(lái)講,更加的方便靈活,更多的語(yǔ)法糖使編寫(xiě) Groovy 代碼更加的簡(jiǎn)潔,而且在 Groovy 中具有函數(shù)式編程的思想。比如:Groovy 中非常重要的閉包 Closure 概念(類似于 C 語(yǔ)言中的函數(shù)指針),可以當(dāng)做一個(gè)函數(shù)也執(zhí)行,也可以當(dāng)做某個(gè)函數(shù)的參數(shù)傳入到函數(shù)中去,也可以當(dāng)做一個(gè)函數(shù)的返回值返回。
想學(xué)好 Gradle,除了必要的 Groovy 知識(shí)基礎(chǔ)以外,還需要了解其他兩個(gè)基礎(chǔ)知識(shí):Android DSL 和 Gradle DSL。
DSL 是 Domain Specific Language(領(lǐng)域特定語(yǔ)言)的縮寫(xiě),其定義是:針對(duì)某一領(lǐng)域,具有受限表達(dá)性的一種計(jì)算機(jī)程序設(shè)計(jì)語(yǔ)言。學(xué)習(xí) Android Gradle,Android DSL 和 Gradle DSL 也是需要學(xué)習(xí)的,好在有官方的文檔 Android DSL 文檔 和 Gradle DSL 文檔,學(xué)習(xí)起來(lái)就比較方便。在這篇文章中,不會(huì)過(guò)多地介紹 Android DSL 和 Gradle DSL,在下篇文章中會(huì)介紹。
好了,廢話不多說(shuō),接下來(lái)就來(lái)學(xué)習(xí) Groovy 的語(yǔ)法基礎(chǔ)吧。為了學(xué)習(xí)的時(shí)候,可以執(zhí)行 gradle 腳本,請(qǐng)先在電腦上配置好 gradle 的環(huán)境變量,這樣就可以方便地執(zhí)行 gradle 腳本了。
二. Groovy 語(yǔ)言基礎(chǔ)
由于篇幅所限,本篇文章也只能作為一個(gè)引子,介紹基礎(chǔ)的 Groovy 語(yǔ)言概念,詳細(xì)的還需要從 Groovy 語(yǔ)言文檔 學(xué)習(xí)。而且我個(gè)人認(rèn)為,如果遇到什么不懂的、不會(huì)的,從官方文檔上學(xué)習(xí)是最好的學(xué)習(xí)途徑;或者至少先從官方文檔上學(xué)習(xí),再去學(xué)習(xí)其他的資料,將自己學(xué)習(xí)的和資料的進(jìn)行對(duì)比思考,這樣會(huì)更有助于個(gè)人的成長(zhǎng)
為了避免無(wú)意義的內(nèi)容,只介紹和 Java 有區(qū)別的地方,相同的地方不作說(shuō)明。
2.1 變量
- Groovy 中聲明的變量,默認(rèn)的修飾符是 public 的
- Groovy 中聲明變量時(shí),如果一行只聲明一個(gè)變量則可以省略末尾的
;,但是如果一行聲明了多個(gè)變量,變量與變量之間則不可以省略; - 在 Groovy 中聲明變量,也可以使用關(guān)鍵字
def,def只是聲明了一個(gè)變量,變量的實(shí)際類型根據(jù)該變量的對(duì)象決定。def和 JavaScript 中的val有點(diǎn)像,從def可以看出 Groovy 也是一門動(dòng)態(tài)語(yǔ)言 - Groovy 中字符串
String,可以使用單引號(hào) 'String',也可以使用雙引號(hào) "String" - 在 Groovy 中的 String,可以通過(guò)
${}做占位符表達(dá)式向字符串中插入值,在{}中寫(xiě)表達(dá)式或變量都可以,使用${}的字符串必須使用雙引號(hào) ""
int version = 1
Boolean isDebug = true
def language = 'groovy'
def message = "Hello from ${language + 1}, the result is ${isDebug}."
task hello {
doLast{
println message
}
}
上面代碼的執(zhí)行輸出是:
> Task :hello
Hello from groovy1, the result is true.
2.2 List
- 因?yàn)樵?Groovy 中沒(méi)有定義任何集合類,所以 Groovy 中的 List 使用的是 JDK 中的 java.util.List
- 在 Groovy 中的一個(gè) List 中可以添加多種類型的對(duì)象元素
- 創(chuàng)建 List 對(duì)象使用
[],而不是 Java 中的{},防止和 Groovy 中的閉包 Closure {}混淆 - 可以通過(guò)
[index]的方式修改和訪問(wèn) List 中的元素 - 可以通過(guò)
<<向 List 中添加元素,<<實(shí)際是leftShift()方法 - 可以通過(guò)負(fù)數(shù),從后向前訪問(wèn) List 中的元素,比如
[-1]表示最后一個(gè)元素 - 可以通過(guò)
[index1, index2]同時(shí)訪問(wèn) List 中的多個(gè)元素,返回結(jié)果仍是一個(gè)List - 可以通過(guò)
[index1..index2]一次性訪問(wèn) List 中某個(gè)范圍內(nèi)的數(shù)組,返回結(jié)果也是一個(gè) List
ArrayList arrayList = ['arrayOne', 'arrayTwo', 'arrayThree']
LinkedList linkedList = ['linkedOne', 'linkedTwo', 'linkedThree']
List list = [1, 2, true]
def listDef = ['one', 2, true, 4, '5']
task helloList {
doLast {
println listDef
println arrayList
println linkedList
println list
println list[0]
println list[-1]
list << 4
println list[-1]
println list[1, 3]
println list[1..3]
}
}
輸出如下所示:
> Task :app:helloList
[one, 2, true, 4, 5]
[arrayOne, arrayTwo, arrayThree]
[linkedOne, linkedTwo, linkedThree]
[1, 2, true]
1
true
4
[2, 4]
[2, true, 4]
2.3 Arrays
Groovy 中的數(shù)組和 Java 中的數(shù)組區(qū)別并不大,也不過(guò)多的做介紹
- Groovy 中的數(shù)組使用
[]初始化,并不使用{},防止和 Groovy 中的閉包 Closure {}混淆 - 數(shù)組不支持
<<向 Arrays 中添加元素
String[] arrayStrings = ["one", "two", 'three'];
def arrayInts = [1, 2, 3] as int[]
task hello {
doLast {
println arrayStrings[0]
println arrayStrings[1]
println arrayStrings[-1]
// arrayStrings << 'four' // Arrays 不支持 <<
println arrayStrings
println arrayInts
}
}
輸出如下所示:
> Task :hello
one
two
three
[one, two, three]
[1, 2, 3]
2.4 Map
- Groovy 中的 Map 是以
:作為 key 和 value 的連接,并且以,做為每一項(xiàng)的分隔符的 - Map 中的 key 既可以是字符串也可以是阿拉伯?dāng)?shù)字
- 可以通過(guò)
[key]和.key的形式訪問(wèn)或向 map 中賦值,訪問(wèn)的時(shí)候如果不存在該key,則會(huì)返回null - 如果以變量作為 key 訪問(wèn) map 時(shí),記得需要加上
()
def maps = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
def mapNums = [1: 'one', 2: 'two', 3: 'three', 100: 'four']
def key = 'name'
def mapKey = [key: 'value']
def mapKey1 = [(key): 'value1']
task helloMaps {
doLast {
println maps['red']
println maps.green
maps['pink'] = '#FF00FF'
maps.yello = '#FFFF00'
println maps['pink']
println maps.yello
println maps.white
println mapNums[1]
println mapNums[100]
println mapNums[5]
println mapKey['key']
println mapKey['name']
println mapKey1['name']
}
}
上述代碼的輸出是
> Task :app:helloMaps
#FF0000
#00FF00
#FF00FF
#FFFF00
null
one
four
null
value
null
value1
2.5 Class 和對(duì)象
Groovy 中的 Class 和 Java 中的 Class 區(qū)別并不大,主要有以下幾個(gè)區(qū)別
- 如果類、方法沒(méi)有修飾符的話,默認(rèn)是
public修飾符的 - 如果類中的變量
fields沒(méi)有被修飾符修飾的話,會(huì)自動(dòng)成為一個(gè)properties,properties是公有的,并且會(huì)自動(dòng)生成該properties的 setter 和 getter 方法 - 在 Java 中,文件名和主類的名稱必須一致,但是 Groovy 中并沒(méi)有這個(gè)限制,且在一個(gè) Groovy 文件中可以出現(xiàn)多個(gè)
public的類 - 在一個(gè) Groovy 文件中可以在類之外定義方法或語(yǔ)句,這種文件就是腳本了
class Student {
def name
def age
private String work
public String lover
def Student(String name) {
this.name = name
}
}
task helloClass {
doLast {
def student = new Student('lijiankun24')
println student.name
println student.getAge()
println student.lover
// println student.getLover() // Student 中并沒(méi)有 getLover() 這個(gè)方法
// println student.getWork() // Student 中并沒(méi)有 getWork() 這個(gè)方法
}
}
輸出結(jié)果如下:
> Task :app:helloClass
lijiankun24
null
null
2.6 函數(shù)
Groovy 中的函數(shù)和 Java 中的函數(shù)并沒(méi)有太大的區(qū)別
- 函數(shù)一定會(huì)有返回值,如果沒(méi)有顯示的使用
return返回值的話,函數(shù)的最后一行語(yǔ)句的執(zhí)行結(jié)果作為值返回,可能返回值是個(gè)null - 如果函數(shù)有參數(shù),調(diào)用函數(shù)的時(shí)候,可以省略函數(shù)的括號(hào),函數(shù)名和參數(shù)之間需要用空格間隔;如果函數(shù)沒(méi)有參數(shù),調(diào)用函數(shù)的時(shí)候就不能省略括號(hào)
- 函數(shù)內(nèi)不可以訪問(wèn)函數(shù)外的變量
def message = 'message'
def printMessage () {
println message
}
void printName(String name) {
println name
}
void printPerson(String name, age) {
println "The name is ${name} and the age is ${age}"
}
task helloFunction {
doLast {
println printName('xiaoming')
printPerson 'xiaoming', 20
// println printMessage() 會(huì)執(zhí)行異常
}
}
輸出結(jié)果如下所示:
> Task :app:helloFunction
xiaoming
null
The name is xiaoming and the age is 20
2.7 閉包 Closure
閉包 closure 是 Java 中沒(méi)有的,也是需要重點(diǎn)學(xué)習(xí)的,學(xué)好 closure 對(duì)理解 Android 中的 Gradle 會(huì)有莫大的幫助
- 閉包
closure的定義如下,其中[closureParameters ->]作為參數(shù)部分,是可以省略的
{ [closureParameters -> ] statements }
-
closure其實(shí)是 Groovy 中groovy.lang.Closure的一個(gè)類 - 閉包
closure可以訪問(wèn)閉包之外的變量 - 閉包
closure可以有三種調(diào)用方式,如下代碼所示 - 閉包
closure的參數(shù)可以省略,默認(rèn)是有個(gè)it參數(shù)的 - 閉包
closure也可以作為另一個(gè)閉包closure的參數(shù)
// 閉包可以訪問(wèn)閉包之外的變量
def message = 'closure is good'
def printMessage = {
println "The message is '${message}'"
}
// 閉包實(shí)際上是一個(gè) `groovy.lang.Closure` 類
Closure<Boolean> booleanClosure = {
return it == 'xiaoming'
}
// 閉包可以省略參數(shù),默認(rèn)有一個(gè) `it` 的參數(shù)
def testClosure = {
println "I am a closure, the params is ${it}."
}
// 閉包可以有多個(gè)參數(shù),參數(shù)可以指定類型,也可以不指定類型
def testClosureParams = { name, int age ->
println "I am a closure, the params is ${name}."
}
// 閉包可以作為另一個(gè)閉包的參數(shù)
def paramsClosure = { name, closure ->
if (closure(name)) {
println 'The input name is xiaoming'
} else {
println 'The input name is not xiaoming'
}
}
task helloClosure {
doLast {
printMessage()
println booleanClosure('xiaoming')
println booleanClosure('test')
// 閉包的三種調(diào)用方式
testClosure 'xiaoming'
testClosure.call('xiaoming')
testClosure('xiaoming')
testClosureParams('xiaoming', 20)
// 閉包 booleanClosure 作為閉包 paramsClosure 的參數(shù)
paramsClosure('xiaoming', booleanClosure)
paramsClosure('test', booleanClosure)
// 可以在調(diào)用閉包的時(shí)候才去定義參數(shù)閉包的定義,使用非常方便簡(jiǎn)潔
paramsClosure('xiaoming', { name ->
name.toUpperCase() == 'XIAOMING'
})
}
}
輸出如下所示
> Task :app:helloClosure
The message is 'closure is good'
true
false
I am a closure, the params is xiaoming.
I am a closure, the params is xiaoming.
I am a closure, the params is xiaoming.
I am a closure, the params is xiaoming.
The input name is xiaoming
The input name is not xiaoming
The input name is xiaoming
Groovy 的基礎(chǔ)知識(shí)就是這么多,如果想學(xué)習(xí)更多的內(nèi)容,建議學(xué)習(xí) Groovy 文檔