1. 程式人生 > >Groovy基礎語法總結

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