使用groovy理解gradle配置文件
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!")}
闭包的调用有两种: 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 15
targetSdkVersion 25
versionCode 1
versionName "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@1700915
Hello,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底层的实现可能会有些出入。 参考文章: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |