Gradle閉包委託總結

作爲一個還處於入門Gradle的小白,記錄一下對Gradle閉包委託的理解。
比如在 《Android Gradle權威指南》 可以看到類似如下代碼段:

static def person(Closure<Person> closure) {
    Person p = new Person()
    closure.delegate = p
    closure.setResolveStrategy(Closure.DELEGATE_FIRST)
    closure(p)
}

class Person {
    String name
    String age
    def dumpPerson() {
        println "name is ${name},age is ${age}"
    }
}

task hello {
    person {
        name = "momo"
        age = "18"
        dumpPerson()
    }
}

首先person方法中傳進了一閉包Closure<Person>,Closure是groovy.lang下的一個抽象類,我們指定了範型Person,這裏爲什麼要指定Person呢?

Closure.class
public V call(Object arguments) {
        return this.call(new Object[]{arguments});
    }

可以調用Closure的call方法來執行閉包,返回值類型即爲指定範型。不過,在as中寫gradle代碼發現並沒有類型強轉的問題(不同類型可以直接賦值),即使不指定範型也不影響執行。不過hello中配置person時會提示Access to 'name' exceeds its access rights

接着看指定代理的代碼:
Person p = new Person()
closure.delegate = p
closure.setResolveStrategy(Closure.DELEGATE_FIRST)

我們創建了一個Person對象,將closure的代理設置爲新創建的Person對象,同時指定處理策略爲代理模式模式優先。
Closure中有三個成員屬性:優先級thisObject>owner>delegate

    private Object delegate;
    private Object owner;
    private Object thisObject;

我們打印一下默認屬性:

static def person(Closure<Person> closure) {

    println "closure.thisObject="+closure.thisObject
    println "closure.owner="+closure.owner
    println "closure.delegate="+closure.delegate
    println "closure.resolveStrategy="+closure.resolveStrategy
}

執行./gradlew hello

closure.thisObject=root project 'Study' //上下文
closure.owner=build_3v90txkmyoa0gezpesdi59gev$_run_closure3@294e7e2d
closure.delegate=build_3v90txkmyoa0gezpesdi59gev$_run_closure3@294e7e2d
closure.resolveStrategy=0 // OWNER_FIRST

那我們不設置處理策略可不可以呢?當然是可以的,不設置會優先級順序處理,比如owner沒有相應方法則會交給delegate處理。

接下來調用了closure(p),一開始我很不理解,既然已經設置了代理對象,那這段代碼是在幹嘛?其實想複雜了,這就是在調用閉包執行。我們還可以用closure()、closure(null)、closure([1,2,3,4])等調用,也就是可以不傳參數或傳任意參數。也可以用Closure的call方法調用執行,比如closure.call(p)

因爲我們用的代理模式,我們傳進的參數相當於閉包中的it參數,配置的時候我們並沒有用到。

所以,這裏如果不用代理而用傳參的方式也可以實現類似效果。代碼改動如下:

static def person(Closure<Person> closure) {
    Person p = new Person()
    closure(p)
}

class Person {
    String name
    String age
    def dumpPerson() {
        println "name is ${name},age is ${age}"
    }
}

task hello {
    person {
        it.name = "momo"
        it.age = "18"
        it.dumpPerson()
    }
}
發佈了47 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章