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()
    }
}
展开阅读全文

没有更多推荐了,返回首页