groovy语言特点:
1、动态弱类型,不需要明确指定类型,也就是说变量可以以多种方式使用,变量和方法的定义使用的都是def关键字。
2、groovy是动态类型语言,也就是说具体的类型取决于对象本身,而不是声明的引用变量,这样做的好处groovy不要求声明变量的类型,方法参数和方法返回值的类型,具体的类型根据赋值或者返回的参数决定,所以我们可以将类型确定的时间推迟到代码运行时。
1、groovy函数定义
使用关键字fun来定义函数,因为groovy为动态弱类型语言,因此不需要声明参数类型和返回类型。
fun apply(map) { map.each { println it.key + ":" + it.value }}
函数的调用
def map = [plugin:"com.androID.application"]apply(map)
我们参数传入的是一个map对象,我们其实可以不用提前定义一个map变量,直接将对象传入:
apply(map) 等价于 apply(plugin:"com.androID.application")
在groovy语言中,对于函数的调用其实可以省略括号,函数名和参数之间直接使用空格即可,因此上面函数调用等价于:
apply(plugin:"com.androID.application")等价于 apply plugin: 'com.androID.application'
2、groovy闭包
具体参考文章:Groovy闭包简述
groovy闭包可以理解为一个可执行代码块的方法,它是一个对象。
基本格式为:
{ line -> println line}
例子:
def clos = {println("Hello World!")}
闭包的调用有两种:
1、可以把闭包理解为一个方法对象,因此将它作为方法来调用
clos()
2、因为闭包也是一个对象类型,因此可以使用它的一个对象方法来调用
clos.call()
对于有参数的闭包:
def clos = {param -> println("Hello ${param}!")}clos("Mirhunana") clos.call("Mirhunana")
需要注意的是:当只有一个参数传递给闭包 的时候,这个参数的声明是可选的,魔术变量 it 代替了声明
def clos = {println("Hello ${it}!")}
如果有多个参数可以声明多个参数,这个跟方法是相同的
def clos = {param1,param2 -> println("Hello ${param1} and ${param1}!")}clos("Mirhunana","Mirhunana")clos.call("Mirhunana","Mirhunana")
我们知道闭包其实就是一个普通的对象类型,因此我们可以跟其他对象的使用方法一样来使用闭包,在方法的调用中,我们当然可以将闭包作为参数来传入。
def defaultConfig(clos) { clos.call()}
调用该函数:
defaultConfig({ applicationID "com.example.demo.demo" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionname "1.0" testInstrumentationRunner "androID.support.test.runner.AndroIDJUnitRunner" })
对于下面这语句,结合我们前面讲的我们应该很容易知道,其他他们就是一些函数的调用了吧。
applicationID "com.example.demo.demo"minSdkVersion 15targetSdkVersion 25versionCode 1versionname "1.0"testInstrumentationRunner "androID.support.test.runner.AndroIDJUnitRunner"
另外,我们知道我们对于函数的调用时可以将括号省略掉的因此,进一步可以得到:
defaultConfig { applicationID "com.example.demo.demo" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionname "1.0" testInstrumentationRunner "androID.support.test.runner.AndroIDJUnitRunner"}
读到这里在看看我们AndroID项目中的build.gradle代码,应该就可以看懂是怎么回事了,原来就是进行的一系列API的调用。
3、Project对象和build.gradle
我们应该知道,build.gradle是对一个Project对象的配置,Project对象与build.gradle是一对一的关系,我们在build.gradle中的所做的一系列调用其实都是针对Project对象进行 *** 作的,也就是前面调用的其实是Project对象的方法来完成对整个项目的配置。
传统上我们都是通过project.apply(map)来实现对project方法的调用,但是在build.gradle脚本中,为什么可以不使用project对象来实现对其方法的调用呢?
Test.groovy文件 ==================================================class DelegateDemo { String author = "Mirhunana" // 定义一个成员方法,方法的参数为闭包类型 // 让closure对象成为DelegateDemo对象的一个代理 def someMethod(closure) { println "The original delegate of closure is: ${closure.delegate}" closure.delegate = this closure() } def greet(words) { println words }}//下面我们来实现对greet方法的调用def delegateDemo = new DelegateDemo()delegateDemo.someMethod { // 此处的delegate可以省略 delegate.greet("Hello," + delegate.author)} =====================================================
上面首先调用someMethod方法,然后使用代理类来实现对greet方法的调用。在调用的过程中可以将delegate省略,即:
delegateDemo.someMethod { greet("Hello," + delegate.author)}
输出:
The original delegate of closure is: Test@1700915Hello,Mirhunana
这样就实现了不需要delegateDemo对象,就可以对其方法进行调用。
另外,closure的delegate的默认值就是调用以closure为参数的方法所在context中的this,看到上面默认打印的代理对象为Test@1700915,原因就是我们someMethod方法的调用所处的context是Test.groovy文件。
如果我们希望默认delegate为delegateDemo对象,我们可以做如下修改:
==================================================class DelegateDemo { String author = "Mirhunana" def someMethod2(closure) { println "The original delegate of closure is: ${closure.delegate}" // 无需设置closure.delegate // 因为closure的delegate默认值已经是DelegateDemo.this closure() } def greet(words) { println words } def test() { def delegateDemo = new DelegateDemo() // 可以看到以闭包对象为参数的方法的调用是在DelegateDemo里面 // 所以闭包的默认delegate为delegateDemo对象 delegateDemo.someMethod2 { // 省略了delegate greet("Hello," + author) } }}//下面我们来实现对greet方法的调用def delegateDemo = new DelegateDemo()delegateDemo.test()==================================================
那么我们build.gradle里面是怎么实现对project对象方法的调用的呢?
class Project { def with(closure) { closure.delegate = this; closure(); } def apply(map) {...} def androID(closure) {...} // ...}def project = new Project()project.with { // build.gradle内容 // 例如: // apply plugin: 'com.androID.application' // androID { // compileSdkVersion 25 // buildToolsversion '25.0.0' // defaultConfig { // applicationID "com.example.demo.demo" // minSdkVersion 15 // targetSdkVersion 25 // versionCode 1 // versionname "1.0" // testInstrumentationRunner "androID.support.test.runner.AndroIDJUnitRunner" // } // buildTypes { // release { // MinifyEnabled false // proguardfiles getDefaultProguardfile('proguard-androID.txt'),'proguard-rules.pro' // } // } // } }
可以看到闭包内的内容就是build.gradle对project对象的 *** 作。这样我们在闭包里面就可以调用project里面的方法了,而且不需要显示的使用project。所以,我们build.gradle里面的内容其实最终转化为一个闭包方法中的内容。
最终附上AndroID项目中build.gradle源码,看完上面的解析之后,再来看这个脚本,是不是感觉很清晰,其实build.gradle脚本的配置就是进行一系类函数API的调用过程。
apply plugin: 'com.androID.application'androID { compileSdkVersion 25 buildToolsversion '25.0.0' defaultConfig { applicationID "com.example.demo.demo" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionname "1.0" testInstrumentationRunner "androID.support.test.runner.AndroIDJUnitRunner" } buildTypes { release { MinifyEnabled false proguardfiles getDefaultProguardfile('proguard-androID.txt'),'proguard-rules.pro' } }}dependencIEs { compile filetree(dir: 'libs',include: ['*.jar']) androIDTestCompile('com.androID.support.test.espresso:espresso-core:2.0',{ exclude group: 'com.androID.support',module: 'support-annotations' }) compile 'com.androID.support:appcompat-v7:25.+' compile 'com.androID.support.constraint:constraint-layout:1.0.0-Alpha7' testCompile 'junit:junit:4.12' compile 'fm.jIEcao:jIEcaovIDeoplayer:5.5.2'}
注意:上面只是根据自己的理解来演示原理,仅供参考,与gradle底层的实现可能会有些出入。
参考文章:
http://www.cnblogs.com/dasusu/p/6635576.html
http://benweizhu.github.io/blog/2015/03/31/deep-into-gradle-in-action-6/
http://www.blogjava.net/BlueSUN/archive/2007/12/22/169580.html
以上是内存溢出为你收集整理的使用groovy理解gradle配置文件全部内容,希望文章能够帮你解决使用groovy理解gradle配置文件所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)