为什么会开始学习闭包,因为在看到这个代码的时候我总是看不懂是什么意思:
1 2 3 4 5 6 gradle.taskGraph.beforeTask { println("任务之前执行" ) } gradle.taskGraph.afterTask {Task task,TaskState state-> println("任务之后执行" ) }
这里你可以点开源码,比如这个afterTask:
1 2 3 4 5 6 class TaskExecutionGraph{ void beforeTask(Closure var1); void beforeTask(Action<Task> var1); void afterTask(Closure var1); void afterTask(Action<Task> var1); }
这里可以看到传入的参数是一个叫Closure
的类,这个就是Groovy里面的闭包. 这里举个闭包的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 //lala.gradle class Person{ String getName(Closure closure){ closure("cc","dd") } } def bibao = { x , y -> println("Hello Closure ,the param valus is: "+x+","+y) } new Persion().getName(bibao) // 运行后输出: Hello Closure ,the param valus is:cc,dd
上面的也可以这么写:
1 2 3 4 5 6 7 8 class Person{ String getName(Closure closure){ closure("cc","dd") } } new Persion().getName{x,y-> println("Hello Closure ,the param valus is: "+x+","+y) }
看了上面这个例子你对闭包应该了解了,和kotlin里面的闭包差不多. 闭包
再回到上面的代码:
1 2 3 gradle.taskGraph.afterTask {Task task,TaskState state-> println("任务之后执行") }
我们在看到源码的时候,看到的是afterTask里面传的参数是Closure,也就是一个闭包,那我们怎么知道这个闭包到底该怎么写呢.这个时候就需要看官方文档了:https://docs.gradle.org/current/javadoc/org/gradle/api/execution/TaskExecutionGraph.html#beforeTask-groovy.lang.Closure- 找到afterTask方法: 可以看到官方文档写清楚了,他的参数有哪些.
现在看另外一个方法: (这个方法是用来配置远程仓库的)
1 2 3 repositories { mavenCentral() }
1 2 3 class Project { void repositories (Closure var1) ; }
可以看到这个方法是属于project对象的. 打开官方文档找下这个方法:
文档里面很清楚的讲了RepositoryHandler
做为闭包的委托传递给闭包.
这里出现了一个新的知识点做为闭包的委托传递给闭包 .闭包委托 : groovy的闭包委托有thisObject,owner,delegate三个属性.当在闭包内调用方法时,由他们来确定使用哪个对象来处理.默认情况owner和delegeta是相等的.但是delegate是可以进行修改的.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def method1 () { println "Context this :${this.getClass()} in root" println "method1 in root" } class Delegate { def method1 () { println "Delegate this : ${this.getClass()} in Delegate" println "method1 in Delegate" } def test (Closure<Delegate> closure) { closure(this ) } } task helloDelegate <<{ new Delegate().test{ println "thisObject :${thisObject.getClass()}" println "owner:${owner.getClass()}" println "delegate:${delegate.getClass()}" method1() it.method1() } } thisObject :class build_apnm7l2hrtoaa0bd51bpb5xcf owner :class build_apnm7l2hrta delegate :class build_apnm7 Context this :class build_apnm7l2hrtoaa0bd51bpb5xcf in root method1 in root Delegate this : class Delegate in Delegate method1 in Delegate
可以看到thisObject优先级是最高的. 在DSL中,比如gradle,一般会指定delegate为当前it,这样我们就可以在闭包中对该it进行配置和方法调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Person { String personName int personAge def dumpPerson () { println "name is ${personName}, age is ${personAge}" } } def person (Closure<Person> closure) { Person p = new Person() closure.delegate = p closure.setResolveStrategy(Closure.DELEGATE_FIRST) closure(p) } task configClosure << { person{ personName="张三" personAge = 20 dumpPerson() } }
在回到上面讲的方法:
1 2 3 repositories { mavenCentral() }
官方文档讲了RepositoryHandler做为了闭包的委托传递给了闭包,所以在{}里面可以用到的方法就都是在RepositoryHandler对象申明的方法了.不信你可以打开RepositoryHandler类看下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public interface RepositoryHandler extends ArtifactRepositoryContainer { FlatDirectoryArtifactRepository flatDir (Map<String, ?> var1) ; FlatDirectoryArtifactRepository flatDir (Closure var1) ; FlatDirectoryArtifactRepository flatDir (Action<? super FlatDirectoryArtifactRepository> var1) ; ArtifactRepository gradlePluginPortal () ; ArtifactRepository gradlePluginPortal (Action<? super ArtifactRepository> var1) ; @Deprecated MavenArtifactRepository jcenter (Action<? super MavenArtifactRepository> var1) ; @Deprecated MavenArtifactRepository jcenter () ; MavenArtifactRepository mavenCentral (Map<String, ?> var1) ; MavenArtifactRepository mavenCentral () ; MavenArtifactRepository mavenCentral (Action<? super MavenArtifactRepository> var1) ; MavenArtifactRepository mavenLocal () ; MavenArtifactRepository mavenLocal (Action<? super MavenArtifactRepository> var1) ; MavenArtifactRepository google () ; MavenArtifactRepository google (Action<? super MavenArtifactRepository> var1) ; MavenArtifactRepository maven (Closure var1) ; MavenArtifactRepository maven (Action<? super MavenArtifactRepository> var1) ; IvyArtifactRepository ivy (Closure var1) ; IvyArtifactRepository ivy (Action<? super IvyArtifactRepository> var1) ; void exclusiveContent (Action<? super ExclusiveContentRepository> var1) ; }
是不是看到了我们熟知的方法:jcenter mavenCentral.所以上面的代码完整点可以这么写:
1 2 3 repositories {RepositoryHandler-> RepositoryHandler.mavenCentral() }