在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ 閉包
Groovy 介紹
腳本類、文件 I/O 和 XML 操作
更多
一些前提知識(shí)
Gradle 工作流程
基本組件
題外話
總結(jié)
Gradle 編程模型及 API 實(shí)例詳解
閉包
Gradle 介紹
閑言構(gòu)建
Groovy 中的數(shù)據(jù)類型

閉包

閉包

閉包的樣子

閉包,英文叫 Closure,是 Groovy 中非常重要的一個(gè)數(shù)據(jù)類型或者說(shuō)一種概念了。閉包的歷史來(lái)源,種種好處我就不說(shuō)了。我們直接看怎么使用它!

閉包,是一種數(shù)據(jù)類型,它代表了一段可執(zhí)行的代碼。其外形如下:

def aClosure = {//閉包是一段代碼,所以需要用花括號(hào)括起來(lái)..
    String param1, int param2 ->  //這個(gè)箭頭很關(guān)鍵。箭頭前面是參數(shù)定義,箭頭后面是代碼  
    println "this is code" //這是代碼,最后一句是返回值,  
   //也可以使用 return,和 Groovy 中普通函數(shù)一樣  
}

簡(jiǎn)而言之,Closure 的定義格式是:

def xxx = {paramters -> code}  //或者  
def xxx = {無(wú)參數(shù),純 code}  這種 case 不需要->符號(hào)  

說(shuō)實(shí)話,從 C/C++ 語(yǔ)言的角度看,閉包和函數(shù)指針很像。閉包定義好后,要調(diào)用它的方法就是:

閉包對(duì)象.call(參數(shù)) 或者更像函數(shù)指針調(diào)用的方法:

閉包對(duì)象(參數(shù))
比如:

aClosure.call("this is string", 100)  或者  
aClosure("this is string", 100)

上面就是一個(gè)閉包的定義和使用。在閉包中,還需要注意一點(diǎn):

如果閉包沒(méi)定義參數(shù)的話,則隱含有一個(gè)參數(shù),這個(gè)參數(shù)名字叫 it,和 this 的作用類似。it 代表閉包的參數(shù)。

比如:

def greeting = { "Hello, $it!" }
assert greeting('Patrick') == 'Hello, Patrick!'

等同于:

def greeting = { it -> "Hello, $it!" }
assert greeting('Patrick') == 'Hello, Patrick!'

但是,如果在閉包定義時(shí),采用下面這種寫法,則表示閉包沒(méi)有參數(shù)!

def noParamClosure = { -> true }

這個(gè)時(shí)候,我們就不能給 noParamClosure 傳參數(shù)了!

noParamClosure ("test")  <==報(bào)錯(cuò)喔!  

Closure 使用中的注意點(diǎn)

1.省略圓括號(hào)

閉包在 Groovy 中大量使用,比如很多類都定義了一些函數(shù),這些函數(shù)最后一個(gè)參數(shù)都是一個(gè)閉包。比如:

public static <T> List<T> each(List<T> self, Closure closure)

上面這個(gè)函數(shù)表示針對(duì) List 的每一個(gè)元素都會(huì)調(diào)用 closure 做一些處理。這里的 closure,就有點(diǎn)回調(diào)函數(shù)的感覺(jué)。但是,在使用這個(gè) each 函數(shù)的時(shí)候,我們傳遞一個(gè)怎樣的 Closure 進(jìn)去呢?比如:

def iamList = [1,2,3,4,5]  //定義一個(gè) List
iamList.each{  //調(diào)用它的 each,這段代碼的格式看不懂了吧?each 是個(gè)函數(shù),圓括號(hào)去哪了?  
      println it
}

上面代碼有兩個(gè)知識(shí)點(diǎn):

  • each 函數(shù)調(diào)用的圓括號(hào)不見(jiàn)了!原來(lái),Groovy 中,當(dāng)函數(shù)的最后一個(gè)參數(shù)是閉包的話,可以省略圓括號(hào)。比如
def  testClosure(int a1,String b1, Closure closure){
      //do something
      closure() //調(diào)用閉包  
}

那么調(diào)用的時(shí)候,就可以免括號(hào)!

testClosure (4, "test", {
   println "i am in closure"
} )  //紅色的括號(hào)可以不寫..

注意,這個(gè)特點(diǎn)非常關(guān)鍵,因?yàn)橐院笤?Gradle 中經(jīng)常會(huì)出現(xiàn)圖 7 這樣的代碼:

http://wiki.jikexueyuan.com/project/deep-android-gradle/images/8.jpg" alt="" />

經(jīng)常碰見(jiàn)圖 7 這樣的沒(méi)有圓括號(hào)的代碼。省略圓括號(hào)雖然使得代碼簡(jiǎn)潔,看起來(lái)更像腳本語(yǔ)言,但是它這經(jīng)常會(huì)讓我 confuse(不知道其他人是否有同感),以 doLast 為例,完整的代碼應(yīng)該按下面這種寫法:

doLast({
   println 'Hello world!'
})

有了圓括號(hào),你會(huì)知道 doLast 只是把一個(gè) Closure 對(duì)象傳了進(jìn)去。很明顯,它不代表這段腳本解析到 doLast 的時(shí)候就會(huì)調(diào)用 println 'Hello world!' 。

但是把圓括號(hào)去掉后,就感覺(jué)好像 println 'Hello world!'立即就會(huì)被調(diào)用一樣!

2.如何確定 Closure 的參數(shù)

另外一個(gè)比較讓人頭疼的地方是,Closure 的參數(shù)該怎么搞?還是剛才的 each 函數(shù):

public static <T> List<T> each(List<T> self, Closure closure)

如何使用它呢?比如:

def iamList = [1,2,3,4,5]  //定義一個(gè) List 變量  
iamList.each{  //調(diào)用它的 each 函數(shù),只要傳入一個(gè) Closure 就可以了。  
  println it
}

看起來(lái)很輕松,其實(shí):

  • 對(duì)于 each 所需要的 Closure,它的參數(shù)是什么?有多少個(gè)參數(shù)?返回值是什么?

我們能寫成下面這樣嗎?

iamList.each{String name,int x ->
  return x
}  //運(yùn)行的時(shí)候肯定報(bào)錯(cuò)!  

所以,Closure 雖然很方便,但是它一定會(huì)和使用它的上下文有極強(qiáng)的關(guān)聯(lián)。要不,作為類似回調(diào)這樣的東西,我如何知道調(diào)用者傳遞什么參數(shù)給 Closure 呢?

此問(wèn)題如何破解?只能通過(guò)查詢 API 文檔才能了解上下文語(yǔ)義。比如下圖 8:

http://wiki.jikexueyuan.com/project/deep-android-gradle/images/9.jpg" alt="" />

圖 8 中:

  • each 函數(shù)說(shuō)明中,將給指定的 closure 傳遞 Set 中的每一個(gè) item。所以,closure 的參數(shù)只有一個(gè)。

  • findAll 中,絕對(duì)抓瞎了。一個(gè)是沒(méi)說(shuō)明往 Closure 里傳什么。另外沒(méi)說(shuō)明 Closure 的返回值是什么.....。

對(duì) Map 的 findAll 而言,Closure 可以有兩個(gè)參數(shù)。findAll 會(huì)將 Key 和 Value 分別傳進(jìn)去。并且,Closure 返回 true,表示該元素是自己想要的。返回 false 表示該元素不是自己要找的。示意代碼如圖 9 所示:

http://wiki.jikexueyuan.com/project/deep-android-gradle/images/10.jpg" alt="" />

Closure 的使用有點(diǎn)坑,很大程度上依賴于你對(duì) API 的熟悉程度,所以最初階段,SDK 查詢是少不了的。

上一篇:Groovy 介紹下一篇:總結(jié)