referece to : http://blog.csdn.net/lzyzsd/article/details/46935063

第一篇博客中,我讲解了关于tasks和构建过程中task的不同阶段。在写完这篇之后,我意识到我应该更详尽的讲述一下Gradle。弄懂语法很重要,免得我们碰到复杂的构建脚本的时候直接晕菜。这篇文章我就会讲解一些语法上的东西。

语法

Gradle脚本是使用Groovy语言来写的。Groovy的语法有点像Java,希望你能接受它。
如果你对Groovy已经很熟悉了,可以跳过这部分了。
Groovy中有一个很重要的概念你必要要弄懂–Closure(闭包)

Closures

Closure是我们弄懂Gradle的关键。Closure是一段单独的代码块,它可以接收参数,返回值,也可以被赋值给变量。和Java中的Callable接口,Future类似,也像函数指针,你自己怎么方便理解都好。。。

关键是这块代码会在你调用的时候执行,而不是在创建的时候。看一个Closure的例子:

def myClosure = { println 'Hello world!' }

//execute our closure
myClosure() #output: Hello world!

下面是一个接收参数的Closure:

def myClosure = {String str -> println str }

//execute our closure
myClosure('Hello world!') #output: Hello world!

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

def myClosure = {println it }

//execute our closure
myClosure('Hello world!') #output: Hello world!

接收多个参数的Closure:

def myClosure = {String str, int num -> println "$str : $num" }

//execute our closure
myClosure('my string', 21) #output: my string : 21

另外,参数的类型是可选的,上面的例子可以简写成这样:

def myClosure = {str, num -> println "$str : $num" }

//execute our closure
myClosure('my string', 21) #output: my string : 21

很酷的是Closure中可以使用当前上下文中的变量。默认情况下,当前的上下文就是closure被创建时所在的类:

def myVar = 'Hello World!'
def myClosure = {println myVar}
myClosure() #output: Hello world!

另外一个很酷的点是closure的上下文是可以改变的,通过Closure#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!'
} #output: Hello from MyClass!

正如你锁看见的,在创建closure的时候,myVar并不存在。这并没有什么问题,因为当我们执行closure的时候,在closure的上下文中,myVar是存在的。这个例子中。因为我在执行closure之前改变了它的上下文为m,因此myVar是存在的。

把closure当做参数传递

closure的好处就是可以传递给不同的方法,这样可以帮助我们解耦执行逻辑。前面的例子中我已经展示了如何把closure传递给一个类的实例。下面我们将看一下各种接收closure作为参数的方法:

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’ }

这里我只想提醒你一下,3和6的写法是不是看起来很眼熟?

Gradle

现在我们已经了解了基本的语法了,那么如何在Gradle脚本中使用呢?先看下面的例子吧:

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
} allprojects {
repositories {
jcenter()
}
}

知道了Groovy的语法,是不是上面的例子就很好理解了?
首先就是一个buildscript方法,它接收一个closure:

def buildscript(Closure closure)

接着是allprojects方法,它也接收一个closure参数:

    def allprojects(Closure closure)

其他的都类似。。。

现在看起来容易多了,但是还有一点不明白,那就是这些方法是在哪里定义的?答案就是Project

Project

这是理解Gradle脚本的一个关键。

构建脚本顶层的语句块都会被委托给Project的实例

这就说明Project正是我要找得地方。
Project的文档页面搜索buildscript方法,会找到buildscript{} script block(脚本块).等等,script block是什么鬼?根据文档

script block就是只接收closure作为参数的方法

继续阅读buildscript的文档,文档上说Delegates to: ScriptHandler from buildscript。也就是说,我们传递给buildscript方法的closure,最终执行的上下文是ScriptHandler。 在上面的例子中,我们的传递给buildscript的closure调用了repositories(closure)和 dependencies(closure)方法。既然closure被委托给了ScriptHandler,那么我们就去ScriptHandler中 寻找dependencies方法。

找到了void dependencies(Closure configureClosure),根据文档,dependencies是用来配置脚本的依赖的。而dependencies最终又是委托到了DependencyHandler

看到了Gradles是多么广泛的使用委托了吧。理解委托是很重要滴。

Script blocks

默认情况下,Project中预先定义了很多script block,但是Gradle插件允许我们自己定义新的script blocks!
这就意味着,如果你在build脚本顶层发了一些{…},但是你在Gradle的文档中却找不到这个script blocks或者方法,绝大多情况下,这是一些来自插件中定义的script block。

android Script block

我们来看看默认的Android app/build.gradle文件:

apply plugin: 'com.android.application'

android {
compileSdkVersion 22
buildToolsVersion "22.0.1" defaultConfig {
applicationId "com.trickyandroid.testapp"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

As we can see, it seems like there should be android method which accepts Closure as a parameter. But if we try to search for such method in Project documentation - we won’t find any. And the reason for that is simple - there is no such method :)

If you look closely to the build script - you can see that before we execute android method - we apply com.android.application plugin! And that’s the answer! Android application plugin extends Project object with android script block (which is simply a method which accepts Closure and delegates it to AppExtension class1).

可以看到,这里有一个android方法,它接收一个closure参数。但是如果我们在Project的文档中搜索,是找不到这个方法的。原因很简单,这不是在Project中定义的方法。
仔细查看build脚本,可以看到在抵用android方法之前,我们使用了com.android.application插件。Android application插件扩展了Project对象,添加了android Script block。
哪里可以找到Android插件的文档呢?Android Tools website或者这里

如果我们打开AppExtension的文档,我们就可以找打build script中使用的方法了属性:
1.compileSdkVersion 22. 如果我们搜索compileSdkVersion,将会找到这个属性. 这里我们给这个属性赋值 “22”。
2.buildToolsVersion和1类似
3.defaultConfig - 是一个script block将会委托给ProductFlavor类来执行。
4.其他
现在我们已经能够理解Gradle脚本的语法了,也知道如何查找文档了。

[Android Pro] Gradle Tips#2-语法的更多相关文章

  1. [Android Pro] Gradle Tips#1-tasks

    reference to : http://trickyandroid.com/gradle-tip-1-tasks/ http://blog.csdn.net/lzyzsd/article/deta ...

  2. [Android Pro] Gradle tip #3-Task顺序

    reference to : http://blog.csdn.net/lzyzsd/article/details/46935405 原文链接 我注意到我在使用Gradle的时候遇到的大多数问题都是 ...

  3. Android studio gradle配置!!!【转】

    转自:http://www.open-open.com/lib/view/open1415793464648.html Gradle 基本概念 首先我们学习几个gradle 的脚本语法,掌握了这几个语 ...

  4. Android使用Gradle命令动态传参完成打包,不需要修改代码

    不得不说,Gradle很强大,有人会问Gradle是什么?这里也不细讲,在我认为他就是一个构建神器.Gradle 提供了: 一个像 Ant 一样的非常灵活的通用构建工具 一种可切换的, 像 Maven ...

  5. 深入理解Android之Gradle

    深入理解Android之Gradle 格式更加精美的PDF版请到:http://vdisk.weibo.com/s/z68f8l0xTYrZt 下载 Gradle是当前非常"劲爆" ...

  6. Android studio gradle 打包 那些事

    总结了一下 目前觉得比较好用的gradle 和一些打包 经验.放在这里. 首先说下 渠道号 这个概念,我们经常会统计我们的api 访问来源 是来自于那个app store,这有利于 我们针对性的推广. ...

  7. Gradle Groovy 基础语法 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  8. Android studio gradle配置完整版(转)

    Android studio gradle配置完整版https://my.oschina.net/u/1471093/blog/539075 Android studio 自定义打包apk名 - pe ...

  9. [转]加速Android Studio/Gradle构建

    加速Android Studio/Gradle构建 android android studio gradle   已经使用Android Studio进行开发超过一年,随着项目的增大,依赖库的增多, ...

随机推荐

  1. PHP跳转页面的几种实现方法详解

    •PHP页面跳转一.header()函数header()函数是PHP中进行页面跳转的一种十分简单的方法.header()函数的主要功能是将HTTP协议标头(header)输出到浏览器.header() ...

  2. 【C语言入门教程】2.1 数据类型(5种基本数据类型),聚合类型与修饰符

    C语言有5种基本的数据类型,分别为 字符型.整型.单精度浮点型.双精度浮点型.空类型. 在不同的操作系统或硬件平台中,这些数据类型的值域范围和所占用的内存是有差异的.这种差异影响了C语言的可移植性能, ...

  3. Android4.4 往短信收件箱中插入自定义短信(伪造短信)

    这段时间稍微有点空闲,把前一段学习Android做过的一些小项目整理整理.虽然没有什么工程量很大的项目,但是对于一个新手,解决这些问题还是花了一段时间.感觉还是非常有记录的意义呢~~~么么哒*—* 今 ...

  4. 采用Atlas+Keepalived实现MySQL读写分离、读负载均衡【转载】

      文章 原始出处 :http://sofar.blog.51cto.com/353572/1601552 ============================================== ...

  5. 避免在WHERE条件中,在索引列上进行计算或使用函数,因为这将导致索引不被使用

    点击(此处)折叠或打开 --在sal列上创建非唯一索引 scott@TESTDB11>create index idx_emp1_sal on emp1(sal); Index created. ...

  6. jQuery学习:用按键移动方块

    <!doctype html> <html> <head> <meta charset="utf-8"> <style typ ...

  7. 深入理解Java虚拟机之读书笔记二 垃圾收集器

    1.对象已死? a.引用计数算法:缺点是它很难解决对象之间的相互循环引用的问题,Java语言中没有选用它. b.根搜索算法(GC Roots Tracing):通过一系列的名为"GC Roo ...

  8. Codeforces 271 Div 2 C. Captain Marmot

    题目链接:http://codeforces.com/contest/474/problem/C 解题报告:给一个n,然后输入4*n个平面坐标系上的点,每四个点是一组,每个点有一个中心,这四个点可以分 ...

  9. Word撤销键(Ctrl+z)无效的解决方法

    最近翻译一本新书,Word2013用的较多,于是发现了一个奇怪的问题,撤销按钮一直是灰色.编辑的时候闪一下,又变为灰色.按Ctrl-Z也同样不管用.中文资源里面的解决方法都是用winword.exe ...

  10. Git-it字典翻译

    Git-it字典翻译 下面的内容翻译自git-it/dictionary 水平有限,翻译欠佳. Git准备工作 创建一个新的文件夹(目录) $ mkdir <目录名称> 切换到这个目录 ( ...