[Android Pro] Gradle Tips#2-语法
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-语法的更多相关文章
- [Android Pro] Gradle Tips#1-tasks
reference to : http://trickyandroid.com/gradle-tip-1-tasks/ http://blog.csdn.net/lzyzsd/article/deta ...
- [Android Pro] Gradle tip #3-Task顺序
reference to : http://blog.csdn.net/lzyzsd/article/details/46935405 原文链接 我注意到我在使用Gradle的时候遇到的大多数问题都是 ...
- Android studio gradle配置!!!【转】
转自:http://www.open-open.com/lib/view/open1415793464648.html Gradle 基本概念 首先我们学习几个gradle 的脚本语法,掌握了这几个语 ...
- Android使用Gradle命令动态传参完成打包,不需要修改代码
不得不说,Gradle很强大,有人会问Gradle是什么?这里也不细讲,在我认为他就是一个构建神器.Gradle 提供了: 一个像 Ant 一样的非常灵活的通用构建工具 一种可切换的, 像 Maven ...
- 深入理解Android之Gradle
深入理解Android之Gradle 格式更加精美的PDF版请到:http://vdisk.weibo.com/s/z68f8l0xTYrZt 下载 Gradle是当前非常"劲爆" ...
- Android studio gradle 打包 那些事
总结了一下 目前觉得比较好用的gradle 和一些打包 经验.放在这里. 首先说下 渠道号 这个概念,我们经常会统计我们的api 访问来源 是来自于那个app store,这有利于 我们针对性的推广. ...
- Gradle Groovy 基础语法 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Android studio gradle配置完整版(转)
Android studio gradle配置完整版https://my.oschina.net/u/1471093/blog/539075 Android studio 自定义打包apk名 - pe ...
- [转]加速Android Studio/Gradle构建
加速Android Studio/Gradle构建 android android studio gradle 已经使用Android Studio进行开发超过一年,随着项目的增大,依赖库的增多, ...
随机推荐
- PHP跳转页面的几种实现方法详解
•PHP页面跳转一.header()函数header()函数是PHP中进行页面跳转的一种十分简单的方法.header()函数的主要功能是将HTTP协议标头(header)输出到浏览器.header() ...
- 【C语言入门教程】2.1 数据类型(5种基本数据类型),聚合类型与修饰符
C语言有5种基本的数据类型,分别为 字符型.整型.单精度浮点型.双精度浮点型.空类型. 在不同的操作系统或硬件平台中,这些数据类型的值域范围和所占用的内存是有差异的.这种差异影响了C语言的可移植性能, ...
- Android4.4 往短信收件箱中插入自定义短信(伪造短信)
这段时间稍微有点空闲,把前一段学习Android做过的一些小项目整理整理.虽然没有什么工程量很大的项目,但是对于一个新手,解决这些问题还是花了一段时间.感觉还是非常有记录的意义呢~~~么么哒*—* 今 ...
- 采用Atlas+Keepalived实现MySQL读写分离、读负载均衡【转载】
文章 原始出处 :http://sofar.blog.51cto.com/353572/1601552 ============================================== ...
- 避免在WHERE条件中,在索引列上进行计算或使用函数,因为这将导致索引不被使用
点击(此处)折叠或打开 --在sal列上创建非唯一索引 scott@TESTDB11>create index idx_emp1_sal on emp1(sal); Index created. ...
- jQuery学习:用按键移动方块
<!doctype html> <html> <head> <meta charset="utf-8"> <style typ ...
- 深入理解Java虚拟机之读书笔记二 垃圾收集器
1.对象已死? a.引用计数算法:缺点是它很难解决对象之间的相互循环引用的问题,Java语言中没有选用它. b.根搜索算法(GC Roots Tracing):通过一系列的名为"GC Roo ...
- Codeforces 271 Div 2 C. Captain Marmot
题目链接:http://codeforces.com/contest/474/problem/C 解题报告:给一个n,然后输入4*n个平面坐标系上的点,每四个点是一组,每个点有一个中心,这四个点可以分 ...
- Word撤销键(Ctrl+z)无效的解决方法
最近翻译一本新书,Word2013用的较多,于是发现了一个奇怪的问题,撤销按钮一直是灰色.编辑的时候闪一下,又变为灰色.按Ctrl-Z也同样不管用.中文资源里面的解决方法都是用winword.exe ...
- Git-it字典翻译
Git-it字典翻译 下面的内容翻译自git-it/dictionary 水平有限,翻译欠佳. Git准备工作 创建一个新的文件夹(目录) $ mkdir <目录名称> 切换到这个目录 ( ...