Groovy基礎語法總結
寫作目的
1.在Android Studio上不可避免的會涉及到Gradle的構建,而Gradle的構建正是基於Groovy之上.
2.相當於Groovy語法上的總結記錄的部落格,後續會繼續更新.
3.更好的總結,有利於知識的鞏固.
簡介
Groovy是從Java衍生出來的,並且執行在Java虛擬機器上的語言.其目標是不管作為指令碼語言,還是程式語言,都可以簡單、直接使用。
Groovy的一些基本語法
列印字串到螢幕上
println 'Hello ,World'
println "Hello ,World"
在Groovy中,字串可以被單引號或者雙引號包裹,都可以表達出字串的含義。
但是他們有不同的用途,雙引號字串可以插入表示式,也就是可以插入佔位符,這些佔位符可以是變數也可以是方法,包含一個單獨變數的佔位符表示式可以只含有“$”字首。
//def 是Groovy中宣告變數的關鍵字
def name = 'Andy'
//在這裡將佔位符替換成name變數
def getting = "Hello , ${name}"
//在這裡是將佔位符替換成 方法結果
def name_size = "Your name is ${name.size()} characters long."
類和成員變數
在Groovy中建立一個類和在Java中建立一個類相似.
//請注意:無論是類,還是成員變數,包括方法都沒有明確的訪問修飾符.
//Groovy中的預設訪問修飾符與Java不同.
//類和方法一樣,是公有的,而類的成員確實私有的.
class MyGroovyClass {
String greeting
void setGreeting(String greeting) {
this.greeting = greeting
}
String getGreeting() {
return greeting
}
}
使用一個類,包括使用一個類的成員變數:
//使用def關鍵字來建立新的變數,建立類也是
def instance =new MyGroovyClass()
instance.setGreeting('Hello World')
//當你試圖直接呼叫一個成員變數時,實際上,你呼叫的是Getter方法,這裡還可以用更簡短的方式表達
instance.getGreeting()
instance.getGreeting
方法
Groovy中的方法就像使用變數一樣,你無須為你的方法定義一個特定的返回型別,但如果為了方法能夠更清新,也可以指定返回物件,在Groovy中,方法的最後一行通常預設返回,即使沒有return關鍵字。
def square(def num){
num * num
}
square 4
在Groovy的方法中,無論是返回型別,還是引數型別都沒有明確的定義。這裡使用了def關鍵字,而不是一個明確的型別,而且在沒有使用return關鍵字的情況下,方法也隱晦的返回了一個值。
Closures
Closures是匿名程式碼塊,可以接受引數和返回值。它們可以被視為變數,被當做引數傳遞給方法。
閉包,是一種資料型別,它代表了一段可執行的程式碼。其外形如下:
def aClosure = {//閉包是一段程式碼,所以需要用花括號括起來..
String param1, int param2 -> //這個箭頭很關鍵。箭頭前面是引數定義,箭頭後面是程式碼
println"this is code" //這是程式碼,最後一句是返回值,
//也可以使用return,和Groovy中普通函式一樣
}
簡而言之,Closure的定義格式是:
def xxx = {paramters -> code} //或者
def xxx = {無引數,純code} //這種情況下是不需要->符號
Closure的呼叫和方法
aClosure.call("this is string",100) 或者
aClosure("this is string", 100)
如果沒有明確給closure指定一個引數,則Groovy會自動新增一個。這個引數通常被稱為it,你可以在所有的closures中使用它,如果呼叫者沒有指定任何引數,則it為空。
集合
在Gradle中使用Groovy時,有兩個重要的集合型別:lists和maps
在Groovy中建立一個新的list非常簡單,無須初始化:
List list = [1,2,3,4,5]
迭代List:
list.each(){
println it
}
另一個集合型別Map,在Gradle中非常重要,它可在多個Gradle設定和方法中使用。
Map pizzaPrices = [margheria:10,prpperoni:12]
並且可以使用get方法來獲取map中的特定專案:
pizzaPrices.get('pepperoni')
pizzaPrices['pepperoni']
而且Gradle也針對get方法做了簡寫
pizzaPrices.pepperoni
任務入門
定義任務
任務屬於一個Project物件,並且每個任務都可以執行task介面。定義一個新任務的最簡單方式是,執行將任務名稱作為其引數的任務方法:
task hello
其建立了任務,但當你執行時,它不會做任何事情。為了建立一個有用的任務,你需要新增一些動作。初學者通常會犯的一個錯誤是像下面這樣建立任務:
task hello{
println 'Hello , world!'
}
當你執行該任務時,會看到輸出如下:
$ gradlew hello
Hello , world!
:hello
從輸出來看,你可能覺得該任務運行了,但實際上,“Hello , world!”在執行該任務之前就已經被打印出來了。
原因就是,在任意Gradle構建中,都有三個階段:初始化階段、配置階段和執行階段。而上述的任務則是設定了任務的配置。
如果你想在執行階段給一個任務新增動作,則應該使用下面的表示法:
task hello << {
println 'Hello , world'
}
唯一的不同就是closure之前的<<,其告知Gradle,程式碼在執行階段執行,而不是在配置階段。
Task在Gradle中有很多簡寫,在Gradle中定義任務的常用方式有以下幾種:
task(hello) << {
println 'Hello , world!'
}
task('hello') << {
println 'Hello ,world!'
}
tasks.create(name: 'hello') << {
println 'Hello , world!'
}
任務剖析
Task介面是所有任務的基礎,其定義了一系列屬性和方法。所有這些都是由一個叫做DefaultTask的類實現的。這是標準的任務實現方式,你建立的每一個新的任務,都是基於DefaultTask的。
每個任務都包含一個Action物件的集合。當一個任務被執行時,所有這些動作會以連續的順序被執行。你可以使用doFirst()和doLast()方法來為一個任務新增動作。這些方法都是以一個closure作為引數,然後被包裝到一個Action物件中的。
task hello {
println 'Configuration'
doLast {
println 'Goodbye'
}
doFirst{
println 'hello'
}
}
當執行hello task時輸出如下:
$ gradlew hello
Configuration
:hello
hello
Goodbye
即使列印“Goodbye”的程式碼在“Hello”的程式碼之前定義,但當執行task時,他們仍會按正確的順序執行。你甚至可以多次使用doFirst()和doLast(),如下所示:
task mindTheOrder{
doFirst{
println 'Not really first'
}
doFirst{
println 'First!'
}
doLast{
println 'Not really last'
}
doLast{
println 'Last!'
}
}
執行這個task的輸出如下:
$ gradlew mindTheOrder
:mindTheOrder
First!
Not really first.
Not really last.
Last!
注意,doFirst()總是新增一個動作到task的最前面,而doLast()總是新增一個動作到最後面,這意味著,當使用這些方法的時候,順序很重要。
當涉及給tasks排序時,可以使用mustRunAfter方法.
當使用mustRunAfter()時,你需要指定,如果兩個任務都被執行,那麼必須有一個任務始終先執行。
task task1 <<{
println 'task1'
}
task task2 <<{
println 'task2'
}
task2.mustRunAfter task1
同時執行task1和task2,不管你指定了什麼樣的順序,task1總是在task2之前執行。
gradlew task2 task1
:task1
task1
:task2
task2
在這兩個任務之間,mustRunAfter()方法不會新增任何依賴,因而我們可以只執行task2而不執行task1。如果你需要一個任務依賴於另一個,那麼可使用dependsOn()方法。
dependsOn()的例子
task task1 << {
println 'task1'
}
task task2 << {
println 'task2'
}
task2.dependsOn task1
當你試圖只執行task2而不執行task1時,結果如下:
$ gradlew task2
:task1
task1
:task2
task2
使用mustRunAfter(),當同時執行task1和task2時,task1總是在task2之前執行,兩者也可以獨立執行。使用dependsOn(),即使在未明確提及的情況下,task2的執行也總是會觸發task1.這是一個重要的區別。
參考
1.Gradle for Android 中文版
2.深入理解Android(一):Gradle詳解
http://www.infoq.com/cn/articles/android-in-depth-gradle