一、脚本文件(build.gradle)

 项目与脚本文件

  当我们执行gradle命令的时候,Gradle会在你执行命令的目录下寻找一个名为build.gradle的文件,这个文件就是Gradle的脚本文件,我们所有的脚本、配置信息都写在这里面,并且一个目录下只能有一个脚本文件。

脚本块

  一个build.gradle文件由若干个指定的脚本块组成,每一个脚本块都代表着不同的功能,Gradle内置了好几种脚本块供我们使用,并且脚本块可以嵌套使用,详情可以查看官方文档,我们来看一段脚本:

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

buildscripte脚本块指定脚本文件所使用的插件来源和远程仓库

repositories脚本块指定了所使用的远程仓库

dependencies指定了相关的依赖关系

allprojects脚本块为所有子项目指定配置信息。

二、项目(project)

  在Gradle中,每一个项目都会有个名为project的实例与之对应,而之前我们说过一个脚本文件就代表着一个项目,所以实际上我们在脚本文件中编写的脚本最后都是委托给project对象处理的,即projectbuild.gradle是一对一的关系。我们可以在脚本文件中通过该实例访问项目脚本的属性、方法和任务,例如project.name可以访问项目的名称、project.version可以访问项目的版本名称、project.rootProject可以访问该项目的父项目等,总之project几乎包含了所有脚本的内容。

在编写脚本的时候,虽然在脚本中直接写属性名称是可以的,但是通过project引用属性名称能够让你的脚本更加清晰易懂,例如project.name会比name更容易让人知道这是一个项目的名称。

三、属性(property)

  在Gradle中,属性分为两种,一种是系统属性,它可以被JVM使用,而另一种我们姑且称之为项目属性,它用于项目的配置。

1.系统属性

  系统属性是可以直接被JVM所使用的,我们可以用它来设置JVM的相关参数,下面按照读取属性的优先级由高到低的方式列出来所有定义方式:

  1. 通过命令行执行gradle -D name=value方式定义系统属性,例如gradle -D org.gradle.java.home=/jdk定义了Gradle运行时所依赖的Java路径。

  2. 在用户目录下创建gradle.properties文件,然后以systemProp.name=value方式定义系统属性,例如用户目录为/home/jerry,那么我们就在该目录下创建gradle.properties文件,并且在文件内定义org.gradle.java.home=/jdk,这样Gradle所以需的Java路径就被定义了。

  3. 在项目目录下创建gradle.properties文件,然后以systemProp.name=value方式定义系统属性,例如项目目录为/HelloGradle,那么我们就在该目录下创建gradle.properties文件,并且在文件内定义org.gradle.java.home=/jdk,这样Gradle所以需的Java路径就被定义了。

2.项目属性

在开发项目的时候我们经常会遇到各种项目属性的配置,例如项目名称、项目版本、打包路径、渠道名称等等,对于这些属性,Gradle为我们提供了多种方式来定义,下面按照读取属性的优先级由高到低列出来所有定义方式:

  1. 通过project.ext.name=value方式定义属性,例如project.ext.channel='360'定义渠道名称为360。

  2. 通过命令行执行gradle -P name=value方式定义属性,例如gradle -P channel=360定义渠道名称为360。

  3. 在用户目录下创建gradle.properties文件,然后以name=value方式定义系统属性,例如用户目录为/home/jerry,那么我们就在该目录下创建gradle.properties文件,并且在文件内定义channel=360,这样就定义了渠道名为360。

  4. 在项目目录下创建gradle.properties文件,然后以name=value方式定义系统属性,例如项目目录为/HelloGradle,那么我们就在该目录下创建gradle.properties文件,并且在文件内定义channel=360,这样就定义了渠道名为360。

3.读取属性

在脚本中读取属性十分容易,对于系统属性,我们可以通过System.properties['name']方式读取,对于项目属性则通过project.name方式读取:

build.gradle:

println System.properties['org.gradle.java.home'] println project.channel

四、任务(task)

  在构建项目的时候,我们如果对整个构建过程进行分解的话,大概可以分解成编译代码、打包、生成文档等过程,Gradle用task来代表这些构建过程,每个步骤对应一个task。如果把项目比喻成一个类,那么task就是类中的方法,我们也可以认为task就是构建项目的原子操作,再细分下去就没有意义了。

Hello world

首先我们来定义一个打印Hello world的task,在build.gradle中编写如下脚本:

build.gradle:

task Hello { doFirst { println 'Hello world' } }

然后我们执行gradle -q Hello命令,-q参数用于过滤多余信息而已,并不是必须的,执行命令后我们会看到如下输出:

> gradle -q Hello Hello world

执行顺序

通过doFirstdoLast来控制task内部脚本的执行顺序

task MyTask { doLast { println 'Execute doLast A' } doFirst { println 'Execute doFirst A' } } MyTask.doFirst { println 'Execute doFrist B' } MyTask.doLast { println 'Execute doLast B' }

执行gradle -q MyTask命令,我们会看到如下输出:

> gradle -q MyTask Execute doFrist B Execute doFirst A Execute doLast A Execute doLast B

  从执行结果,我们可以看出MyTask的行为被我们修改了,也就是说Gradle允许你在定义完task之后动态添加更多的行为,其中MyTask.doFirst {...}新增的doFrist会被添加到执行队列的头部,而MyTask.doLast {...}新增的doLast会被添加到执行队列的尾部,所以我们会看到先打印Execute doFirst again,最后打印Execute doLast again

如果我们不关心脚本的执行顺序,我们可以用<<来快速定义task,<<等价于doLast,也就是说下面的两种定义方式是等价的:

task Task1 << { println 'Hello' }
task Task2 { doLast { println 'Hello' } }

动态定义

3.times { i -> task "MyTask$i" << { println "My task $i" } }
> 提示:这段代码是Groovy的语法,它的作用相当于Java的`for(int i = 0; i < 3; i++)`。 
执行`gradle -q MyTask0 MyTask1 MyTask2`命令,我们会看到如下输出: ~~~ > gradle -q MyTask0 MyTask1 MyTask2 My task 0 My task 1 My task 2 ~~~

依赖关系

  task之间可以通过关键字dependsOn指定依赖关系,比如负责打包的task A依赖于编译class文件的task B,这时候当我们允许task A的时候,task B会被先执行,然后才执行task A。

单个依赖

首先我们来看一个最简单的依赖关系,我们称他为单个依赖,因为一个task的运行只依赖于另一个依赖:

task task2 << { println 'Execute task2' } task task1(dependsOn: task2) << { println 'Execute task1' }

执行gradle -q task1命令,我们会看到如下输出:

> gradle -q task1 Execute task2 Execute task1

多个依赖

如果我们想指定更多的依赖关系的话,可以用”[ ] “定义多个task,看如下脚本:

task task2 << { println 'Execute task2' } task task3 << { println 'Execute task3' } task task4 << { println 'Execute task4' } task task1(dependsOn: [task2, task3, task4]) << { println 'Execute task1' }

执行gradle -q task1命令,我们会看到如下输出:

> gradle -q task1 Execute task2 Execute task3 Execute task4 Execute task1

指定类型

在定义task的时候,我们可以通过关键字type为task指定一种类型,task会根据不同类型具有不同的功能,并且Gradle内置了很多实用的task类型,比如Copy类型让task具有拷贝文件的功能,task的类型指定有点像继承的关系:

task copyFile(type: Copy) { from '/home/xxx/' into '/home/yyy/' include 'file1.txt' rename 'file1.txt', 'file2.txt' }

执行gradle copyFile命令,然后该task就会从/home/xxx/目录下将file1.txt文件复制到/home/yyy/目录下,并且重命名为file2.txt。更多的task类型可以查看Gradle的官方文档。

查看task

最后你可以通过gradle tasks命令查看有多少的task可用,并且父项目可以直接操作子项目的task,反过来却不行

五、依赖(dependency)

很多时候我们的项目会依赖到一些第三方库,Gradle为我们提供了3种方式配置依赖项。

1.依赖本地文件

假设我们在项目的libs目录下有个库叫做mylib.jar,我们可以通过以下方式让项目依赖这个库:

dependencies { compile files('libs/mylib.jar') }

通过上面的脚本,我们的项目在编译的时候会自动依赖mylib.jar库。


如果你的libs下面有好几个文件需要依赖,可以通过以下方式让项目一次性依赖所有库文件:

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) }

2.依赖网络库

我们可以通过Gradle依赖网络上的第三方库,这些库一般都会保存在一个网络仓库中,例如mavenjcenter,使用网络上的库带来的好处就是我们可以简单修改版本号就可以更新到最新版的库,并且也省去了我们手动去复制文件。

想要依赖网络仓库里面的第三方库,我们需要知道3个信息:group、name和version。

  • group:第三方库的组织名称。

  • name:第三方库的名称。

  • version:第三方库的版本。

现在假设我们有一个第三方库在maven仓库下,它的信息如下:

group: com.hjdzone.lib name: mylib version: 1.0.0

想要使用这个第三方库,我们可以编写如下脚本:

repositories { mavenCentral() } dependencies { compile 'com.hjdzone.lib:mylib:1.0.0' }

六、插件(plugin)

  严格上来说Gradle只是一个构建框架,并没有提供任何真正的构建功能,构建任务其实是通过插件实现的,不同的插件会根据不同构建需求定义各种task供我们使用,并且Gradle已经提供了大量的插件,大多数情况下我们无需自己重写plugin,只需要简单地指定plugin就可以使用了。其实在前面的例子中我们就用到了名为java的插件,接下来我们就继续以之前的HelloGradle项目为例,介绍插件的用法。

  首先你必须在build.gradle中声明使用java插件: 

apply plugin: 'java'

  Gradle遵循约定优于配置的原则,所以你的项目结构必须符合插件的要求才能够被插件所识别,例如java插件要求我们的代码必须放在src/main/java 目录下,资源文件必须放在src/main/resources目录下,测试代码必须放在src/test/java目录下,测试资源必须放在src/test/resources目录下:

HelloGradle build.gradle src/main/java/Main.java src/main/resources/logo.png src/test/java/TestMain.java src/test/resources/logo.png

  java插件提供了各种脚本块用于配置项目,例如你可以通过插件提供的脚本块sourceSets修改项目的结构:

sourceSets { main { java './java' resources './resources' } }

  该脚本把代码目录指定到了./java目录下,把资源文件目录指定到了./resources目录下。

java插件为我们提供了一套完整的构建任务,我们可以通过执行gradle tasks命令查看可用的task:

官方文档

参考:Gradle 快速入门

Gradle详解的更多相关文章

  1. Gradle 详解

    Gradle简单来说,就是工程的管理,帮我们做了依赖,打包,部署,发布等工作.就像一个管家管理我们的项目,我们只用关心写代码就可以了. 1 gradle-wraaper.properties 主工程的 ...

  2. build.gradle 详解(一)

    简述: 1) Java 开发中有两个大名鼎鼎的项目构建 ANT.Maven. 2) Google 推荐使用的 Android studio 是采用 Gradle 来构建项目.Gradle 是一个非常先 ...

  3. Gradle详解+Groovy

    http://blog.csdn.net/u014761700/article/details/51867939

  4. Android Gradle 自定义Task 详解

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76408024 本文出自[赵彦军的博客] 一:Gradle 是什么 Gradle是一 ...

  5. Android Studio系列教程五--Gradle命令详解与导入第三方包

    Android Studio系列教程五--Gradle命令详解与导入第三方包 2015 年 01 月 05 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://s ...

  6. 安卓集成发布详解(二)gradle

    转自:http://frank-zhu.github.io/android/2015/06/15/android-release_app_build_gradle/ 安卓集成发布详解(二) 15 Ju ...

  7. Android Gradle manifestPlaceholders 占位符详解

    Android Gradle manifestPlaceholders 占位符详解 在实际项目中,AndroidManifest里十几个地方的值是需要动态的改变(生成apk文件的时候).如果每次去改也 ...

  8. Android学习之基础知识二(build.gradle文件详解)

    一.详解build.gradle文件 1.Android Studio是采用Gradle来创建项目的,Gradle是非常先进的构建的项目的工具,基于Groovy领域特定的语言(DSL)来声明项目配置, ...

  9. Android Studio gradle配置详解

    android gradle配置详解 AppExtension类及其属性 可能大部分人看到AppExtension类会感觉到非常的陌生,其实我们在app中的build.gradle中填写配置信息的时候 ...

随机推荐

  1. std::string 赋值为nullptr引起程序崩溃

    一个错误排查两天,std::string赋初值时最好为"", 如果赋初值为nullptr,因为std::string不能和nullptr作比较,所以后面用的时候会引起崩溃. 佩服我 ...

  2. 【刷题】BZOJ 3295 [Cqoi2011]动态逆序对

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  3. 学习Spring Boot:(九)统一异常处理

    前言 开发的时候,每个controller的接口都需要进行捕捉异常的处理,以前有的是用切面做的,但是SpringMVC中就自带了@ControllerAdvice ,用来定义统一异常处理类,在 Spr ...

  4. 【agc006f】Blackout(神仙题)

    [agc006f]Blackout(神仙题) 翻译 给定一个\(n*n\)的网格图,有些格子是黑色的.如果\((x,y),(y,z)\)都是黑色的,那么\((y,x)\)也会被染黑,求最终黑格子数量. ...

  5. 【BZOJ2830/洛谷3830】随机树(动态规划)

    [BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...

  6. Luogu 2801 教主的魔法 | 分块模板题

    Luogu 2801 教主的魔法 | 分块模板题 我犯的错误: 有一处l打成了1,还看不出来-- 缩小块大小De完bug后忘了把块大小改回去就提交--还以为自己一定能A了-- #include < ...

  7. HDU 2087 剪花布条(字符串匹配,KMP)

    HDU 2087 剪花布条(字符串匹配,KMP) Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出 ...

  8. 八、java常用类

    目录 一.字符串相关类 String类 StringBuffer类 二.基本数据类型包装类 三.Math类 四.File类 五.枚举类 一.字符串相关类 1.String类 java.lang.Str ...

  9. openstack中的server

    一.HTTP server 主要是horizon模块,horizon是基于Python Django搭建的web应用,其运行于Apache网络服务器上(当然也可以运行在其他web服务器上),主要功能就 ...

  10. NDKr10的各种BUG

    NDKr10有几个BUG,所以推荐使用NDKr9 bug1:不支持srand() bug2: 链接异常,找不到stpcpy()