使用gradle構建android工程分爲兩個步驟,第一是配置階段,定義project和task的屬性和相互依賴關係;第二階段是執行階段,根據相應的定義執行project和task。android
雖然不少時候咱們按照現成的模板寫就能夠了,可是若是能讀懂groovy語法,咱們就能夠觸類旁通,寫出本身想要的效果。閉包
groovy語言中有兩大概念,第一是bean概念,即groovy會爲每個字段都默認生成getter和setterapp
class GroovyBeanExample {
private String name
}
task testbean{
def bean = new GroovyBeanExample()
bean.name = 'this is name'
println bean.name//輸出 this is name
}
能夠看到,即便咱們爲一個class定義了一個private的字段,咱們在讀寫的時候依然可使用「.字段」的方式,實際上就是使用默認的getter和setter進行讀寫的。gradle
第二是閉包的delegate(代理)機制,使用閉包代理機制,咱們能夠將閉包中代碼的做用對象設置爲其餘任意的對象。ui
class Child { private String name } class Parent { Child child = new Child(); void configChild(Closure c) { c.delegate = child c.setResolveStrategy Closure.DELEGATE_FIRST c() } } task testClosure{ def parent = new Parent() parent.configChild { name = "child name" } println parent.child.name//經過代理機制,name成了child的屬性 }
在上面的例子中,當咱們調用configChild()方法時,咱們並無指出name屬性是屬於Child的,可是它的確是在設置Child的name屬性。事實上光從該方法的調用中,咱們根本不知道name是屬於哪一個對象的,你可能會認爲它是屬於Parent的。真實狀況是,在默認狀況下,name的確被認爲是屬於Parent的,可是咱們在configChild()方法的定義中作了手腳,使其再也不訪問Parent中的name(Parent也沒有name屬性),而是Child的name。在configChild()方法中,咱們將該方法接受的閉包的delegate設置成了child,而後將該閉包的ResolveStrategy設置成了DELEGATE_FIRST。這樣,在調用configChild()時,所跟閉包中代碼被代理到了child上,即這些代碼其實是在child上執行的。此外,閉包的ResolveStrategy在默認狀況下是OWNER_FIRST,即它會先查找閉包的owner(這裏即parent),若是owner存在,則在owner上執行閉包中的代碼。這裏咱們將其設置成了DELEGATE_FIRST,即該閉包會首先查找delegate(本例中即child),若是找到,該閉包便會在delegate上執行。對於上面的showDescription3,即是這種狀況。固然,實際狀況會稍微複雜一點,好比showDescription3()方法會在內部調用showDescription3的configure()方法,再在configure()方法中執行閉包中的代碼。this
你可能會發現,在使用Gradle時,咱們並無像上面的parent.configChild()同樣指明方法調用的對象,而是在build.gradle文件中直接調用task(),apply()和configuration()方法等,這是由於在沒有說明調用對象的狀況下,Gradle會自動將調用對象設置成當前Project。好比調用apply()方法和調用project.apply()方法的效果是同樣的。查查Gradle的Project文檔,你會發現這些方法都是Project類的方法。spa
另外舉個例子,對於configurations()方法(它的做用咱們將在後面的文章中講到),該方法實際上會將所跟閉包的delegate設置成ConfigurationContainer,而後在該ConfigurationContainer上執行閉包中的代碼。再好比,dependencies()方法,該方法會將所跟閉包的delegate設置成DependencyHandler。代理
還有,Project還定義了configure(Object object,Closure configureClosure)方法,該方法是專門用來配置對象的(好比Task),它會將configureClosure的delegate設置成object,以後configureClosure中的執行代碼實際上是在object上執行的。和Groovy Bean同樣,delegate機制的一個好處是能夠增長所建立DSL的可讀性。code