Gradle构建中的重要语法

from:Gradle构建中的重要语法


上一篇博客中,我们简单的利用Gradle从零开始构建了一个简单的Android app项目,对build.gradle中的有些语法,可能不是很熟悉,所以很有必要理解Gradle的重要语法。通过这边文章,希望能读懂简单build,gradle,最重要的是如何查阅文档。


‘’,“”,’‘’ ‘’‘


看gradle脚本的时候,发现有的字符串是’’,有的是“”,还有的是’’’ ‘’’ 他们都用在什么地方呢?

单引号’’中的内容严格对应Java中的String,不对$符号进行转义。

双引号””的内容则和脚本语言的处理有点像,如果字符中有

号的话,则它会表达式先求值。例如:

1
2


def x = 1
defdoubleQuoteWithDollar = "I am $x dolloar" //输出I am 1 dolloar

三个引号’’’xxx’’’中的字符串支持随意换行


闭包Closures


Gradle脚本是利用Groovy语言编写的,而Groovy语言又是对java语言的扩展,使其可以像脚本一样运行,而不需要编译。Gradle脚本中最晦涩的莫过于Groovy中的闭包了。


什么是闭包


Closure是一段单独的代码块,它可以接收参数,返回值,也可以被赋值给变量。其实Groovy的闭包更象是一个“方法指针”,代码在某处被定义,但不执行,然后在其后的调用处执行。


闭包格式


下面是一个闭包的简单例子:




def myClosure = { println 'Hello world!' }
 
/*执行*/
myClosure()

//执行结果: Hello world!

接收参数的闭包:闭包的参数声明写在‘->’符号前,调用闭包的的标准写法是:闭包名.call(闭包参数),call也可以省略




def myClosure = {println 'hello world' }
 
myClosure()
 
//执行结果: Hello world!


如果Closure只接收一个参数,可以使用it来引用这个参数:



def myClosure = {println it }
 
myClosure('Hello world!')
 
//执行结果: Hello world!


接收多个参数的Closure:可以不指定参数类型




def myClosure = {str, num -> println "$str : $num" }
 
myClosure('my string', 21)
 
//执行结果: my string : 21


可以使用当前上下文中的变量:



def myVar = 'Hello World!'
def myClosure = {println myVar}
myClosure()
 
//执行结果: Hello world!

上下文可以通过setDelegate()改变:


def myClosure = {println myVar} //I'm referencing myVar from MyClass class
MyClass m = new MyClass()
myClosure.setDelegate(m)
myClosure()
 
class MyClass {
    def myVar = 'Hello from MyClass!'
}
 
//执行结果: Hello from MyClass!


在创建closure的时候,myVar并不存在。这并没有什么问题,因为当我们执行closure的时候,在closure的上下文中,myVar是存在的.

## 闭包做参数

1.只接收一个参数,且参数是closure的方法: myMethod(myClosure)

2.如果方法只接收一个参数,括号可以省略: myMethod myClosure

3.可以使用内联的closure: myMethod {println ‘Hello World’}

4.接收两个参数的方法: myMethod(arg1, myClosure)

5.和4类似,单数closure是内联的: myMethod(arg1, { println ‘Hello World’ })

6.如果最后一个参数是closure,它可以从小括号从拿出来: myMethod(arg1) { println ‘Hello World’ }

Gradle脚本中大量使用了2.3.6所示的写法。


build.gradle中的相关解释


上一篇博客中build.gradle的相关片段如下





buildscript{
    println '------buildscript configire phase---------'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'

    }

}


现在应该很好理解了吧,buildscript就是一个以闭包为参数的方法,省略了(),而且使用了内联闭包,参考上面的方法3。

现在还有一个疑问buildscript方法是谁定义的?

查阅Gradle DSL文档(可参考第一篇博客中的方法获取相关文档)docs/dsl/index.html,如下图所示



可知buildscript委托给了project实现,仔细查看了该文档,未发现 android方法,那么它是怎么来的呢?

别忘记了,前面还引入了一个插件
apply plugin: 'com.android.application'

android 方法应该是由他提供的了。但是我在文档中也没找到android方法,很奇怪。从他的用法上看,是接受了一个闭包作为其唯一参数。而且这个闭包的上下文被设置为了AppExtension。其文档android-gradle-plugin-dsl/com.android.build.gradle.AppExtension.html,如下图所示