一、Gradle 基础

本文介绍了Gradle的基础概念,包括Gradle的分布、wrapper的添加与使用、GradleUserHomedirectory和ProjectRootdirectory的作用,以及Groovy语法的基础知识,如变量、数据类型、流程控制和类定义。
摘要由CSDN通过智能技术生成

一、Gradle 基础
二、Gradle 构建
三、Task 编写和使用
四、Plugin 编写和使用


Gradle 基础

Gradle 基础

  1. Projects:像应用或者库一样,一个Gradle项目是一个可以编译的软件。单个项目本身是根目录,如果多个项目时,那么应该由一个根项目和多个子项目构成。

  2. Build Scripts:构建加脚本详细记录Gradle如何完成一个项目的构建。每个项目至少包含一个构建的脚本。

  3. Dependency Management:依赖管理可以自动解析项目声明好的外部资源依赖。

  4. Tasks:任务是编译代码或者运行测试的基本工作单元。在一个插件或者构建脚本中,每个项目至少需要执行一个任务。

  5. Plugins:插件可以用于扩展Gradle的功能,并可选择性地为项目增加额外的任务。

1.1 Gradle 的基础概念

1.1.1 Distribution

Distribution,即Gradle发布版本。每个Gradle版本发布时,一般会有三个项目,分别是src(源码)、bin(精简可运行包)和all(不仅包含可运行文件,还包含sample以及用户文档)。
在这里插入图片描述
Gradle是基于JVM的运行程序,本质上是一个JVM程序,通过bin下文件,运行JVM程序,并加载lib下所需的jar包。
在这里插入图片描述

1.1.2 Wrapper

因为Gradle版本较多,而且Gradle文件比较大,如果随项目一起,不是很方便。这时,就需要wrapperwrapper是一个脚本,它会通过一些配置项和执行文件,在实际构建项目时,首先会检查本地是否有符合要求的gradle distribution,如果没有,则会下载,如果已经存在,则直接构建项目。这样,开发人员可以快速启动并运行 Gradle 项目。

1.1.2.1 添加 wrapper

执行$ gradle wrapper命令可以添加wrapper,添加wrapper后,文件目录如下:

├── a-subproject
│   └── build.gradle
├── settings.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
  • gradle-wrapper.jar:下载Gradle distributionwrapper jar文件;
  • gradle-wrapper.properties:配置wrapper属性的属性文件,比如:graddle distribution版本、是否使用代理、Gradle distribution路径等;
  • gradlew, gradlew.bat:执行wrapper构建的shell以及bat脚本;

哪怕没有gradle的运行环境,你也可以执行wrapper来完成构建的工作。

1.1.2.2 使用 wrapper
$ gradlew.bat build
Downloading httpsservices.gradle.orgdistributionsgradle-5.0-all.zip
.....................................................................................
Unzipping CDocuments and SettingsClaudia.gradlewrapperdistsgradle-5.0-allac27o8rbd0ic8ih41or9l32mvgradle-5.0-all.zip to CDocuments and SettingsClaudia.gradlewrapperdistsgradle-5.0-alac27o8rbd0ic8ih41or9l32mv
Set executable permissions for CDocuments and SettingsClaudia.gradlewrapperdistsgradle-5.0-allac27o8rbd0ic8ih41or9l32mvgradle-5.0bingradle

BUILD SUCCESSFUL in 12s
1 actionable task 1 executed

如果本地没有gradle 运行环境,那么Wrapper 会下载distribution到本地文件系统。以后,只要distribution url没有改变,那么distribution可以重复使用。

1.1.2.3 升级wrapper
  1. 修改gradle-wrapper.propertiesdistributionUrl属性;
  2. 执行命令,比如:.gradlew wrapper --gradle-version latest或者.gradlew wrapper --gradle-version 8.5

1.1.3 Gradle User Home directory 和 Project Root directory

Gradle主要依靠Gradle User Home Project Root两个文件夹管理以及展开工作。
在这里插入图片描述

1.1.3.1 Gradle User Home directory

默认情况下,Gradle User Home存储位置位于:~.gradleCUsersUSERNAME.gradle,文件夹内保存全局的配置文件、初始化脚本、缓存以及日志文件。如果想要修改路径,可以通过设置环境变量GRADLE_USER_HOME修改。

其文件夹结构大体如下:

├── caches ①
│   ├── 4.8 ②
│   ├── 4.9 ②
│   ├── ⋮
│   ├── jars-3 ③
│   └── modules-2 ③
├── daemon ④
│   ├── ⋮
│   ├── 4.8
│   └── 4.9
├── init.d ⑤
│   └── my-setup.gradle
├── jdks ⑥
│   ├── ⋮
│   └── jdk-14.0.2+12
├── wrapper
│   └── dists ⑦
│       ├── ⋮
│       ├── gradle-4.8-bin
│       ├── gradle-4.9-all
│       └── gradle-4.9-bin
└── gradle.properties ⑧
  1. 全局缓存目录(不包含项目特有的缓存);
  2. 不同版本缓存目录(比如支持增量编译);
  3. 共享的缓存;
  4. Gradle Daemon注册表和日志;
  5. 全局初始化脚本;
  6. 工具链支持下载的JDK
  7. Gradle Wrapper下载的Distributions
  8. 全局配置文件;
1.1.3.2 Project Root directory

Project Root包含项目所有源文件的同时,还包含像.gradlebuildgradle创建的文件和文件夹。

其文件夹结构大体如下:

├── .gradle                 Ⅰ
│   ├── 4.8                 Ⅱ
│   ├── 4.9                 Ⅱ
│   └── ⋮
├── build                   Ⅲ
├── gradle
│   └── wrapper             Ⅳ
├── gradle.properties       Ⅴ
├── gradlew                 Ⅵ
├── gradlew.bat             Ⅵ
├── settings.gradle.kts     Ⅶ
├── subproject-one          Ⅷ
   └── build.gradle.kts    Ⅸ
├── subproject-two          Ⅷ
   └── build.gradle.kts    Ⅸ
└── ⋮
  1. Gradle创建的项目特有缓存文件夹;
  2. 版本专有缓存(比如支持增量编译);
  3. 项目中Gradle创建的编译目录;
  4. 保存Gradle WrapperJAR文件以及配置文件;
  5. 项目特有的配置文件;
  6. 使用Wrapper编译的脚本;
  7. 定义子项目的项目设置文件;
  8. 一般情况下,一个或多个子项目组成一个完整的项目;
  9. 每个子项目自己的Gradle编译脚本;

1.1.4 Client

client 进程是个轻量级进程,每次构建开始都会创建这个进程,构建结束会销毁这个进程。

1.1.5 Daemon

Daemon不可以直接与用户交互控制,而是作为后台程序运行。Gradle使用JVMJVM运行需要加载一些必要的支持库。这些库加载需要花费大量时间,所以,JVM的启动通常比较缓慢,针对该问题,提出Gradle Daemon概念解决该问题。Daemon常驻于后台,之所以可以有效加快构建的速率,主要是因为:

  • 缓存构建过程中项目的信息
  • 在后台运行,避免每个Gradle构建重新启动JVM
  • 可以从JVM持续性运行优化获益
  • 监控文件系统,省略重新构建时一些重复构建工作

Gradle DameonGradle Client之间通过Socket通信

1.2 Groovy 语法基础

Groovy 教程 (w3schools.cn)

Groovy 是⼀种基于 JVM 的动态语⾔,他的语法和 Java 相似,最终也是要编译 .classJVM 上运⾏。Groovy 完全兼容 Java 并且在此基础上添加了很多动态类型和灵活的特性,⽐如⽀持闭包,⽀持DSL(领域特 定语⾔),是⼀⻔⾮常灵活的动态脚本语⾔。

1.2.1 变量

Groovy中⽤def关键字来定义变量,可以不指定变量的类型,默认访问修饰符是public

def a = 1;
def int b = 1;
def c = "hello world";

1.2.2 数据类型

Groovy中的数据类型主要有以下⼏种:

  • Java中的基本数据类型
  • Groovy中的容器类
  • 闭包
1.2.2.1 字符串

Groovy种有两种字符串类 型,普通字符串Stringjava.lang.String)和插值字符串GStringgroovy.lang.GString)。

Groovy中单引号字符串和双引号字符串都可以定义⼀个字符串常量,只不过单引号字符串不⽀持插值。要想插值可以使⽤双引号字符串,插值指的是替换字符串中的占位符,占位符表达式为 ${} 或 者以 $ 为前缀。

def name = 'Android进阶之光'
println "hello ${name}"
println "hello $name"

三引号字符串可以保留⽂本的换⾏和缩进格式,不⽀持插值。

def name = '''Android进阶之光
 Android进阶解密
Android进阶?'''
println name
1.2.2.2 List

Groovy没有定义⾃⼰的集合类,它在Java集合类的基础上进⾏了增强和简化。GroovyList对应Java中的List接⼝,默认的实现类为Java中的ArrayList

def number = [1, 2, 3] 
assert number instanceof List 
def linkedList = [1, 2, 3] as LinkedList 
assert linkedList instanceof java.util.LinkedList

可以使⽤as操作符来显式指定List的实现类为java.util.LinkedList。 获取元素同样要⽐Java要简洁些,使⽤ [] 来获取List中具有正索引或负索引的元素。

def number = [1, 2, 3, 4] 
assert number [1] == 2
assert number [-1] == 4 // -1 列表最后一个元素
number << 5 // 2 列表末尾追加⼀个元素
assert number [4] == 5
assert number [-1] == 5
1.2.2.3 Map

创建Map同样使⽤ [] ,需要同时指定键和值,默认的实现类为java.util.LinkedHashMap

def name = [one: '魏⽆羡', two: '杨影枫', three: '张⽆忌'] 
assert name['one'] == '魏⽆羡'
assert name.two == '杨影枫'

1.2.3 流程控制语句

1.2.3.1 for 循环

Groovy⽀持Javafor(int i=0;i<N;i++)for(int i:array)形式的循环语句,另外还支持for in loop形式,支持遍历范围、列表、Map、数组和字符串等多种类型。

// 遍历范围
def x = 0
for ( i in 0..3 ) {
 x += i
}
assert x == 6
// 遍历列表
def x = 0
for ( i in [0, 1, 2, 3] ) {
 x += i
}
assert x == 6
// 遍历 Map 中的值
def map = ['a':1, 'b':2, 'c':3]
x = 0
for ( v in map.values() ) {
 x += v
}
assert x == 6

1.2.3.2 switch语句

Groovy中的Switch语句不仅兼容Java代码,还可以处理更多类型的case表达式。case表达式可以是字符串、列表、范围、Integer等等

def x = 16
def result = ""
switch ( x ) {
 case "ok":
 result = "found ok"
 case [1, 2, 4, 'list']:
 result = "list"
 break
 case 10..19:
 result = "range"
 break
 case Integer:
 result = "integer"
 break
 default:
 result = "default"
}
assert result == "range"

1.2.4 方法

⽅法使⽤返回类型或def关键字定义,⽅法可以接收任意数量的参数,这些参数可以不申明类型, 如果不提供可⻅性修饰符,则该⽅法为public。 ⽤def关键字定义⽅法。

def add(int a,int b) {
    println a+b // 3
} 
def minus(a,b) {// 2
    println a-b
} 
add (1,2)
minus 1,2 // 1 

如果指定了⽅法返回类型,可以不需要def关键字来定义⽅法。

int minus(a,b) {
    return a-b
} 
def number=minus 1,2
println number

如果不使⽤return,⽅法的返回值为最后⼀⾏代码的执⾏结果。

int minus(a,b) {
    a-b //4
}

从上⾯两段代码中可以发现Groovy中有很多省略的地⽅:

  1. 语句后⾯的分号可以省略。
  2. ⽅法的括号可以省略,⽐如注释1和注释3处。
  3. 参数类型可以省略,⽐如注释2处。
  4. return可以省略掉,⽐如注释4处。

1.2.5 闭包

Groovy中的闭包是⼀个开放的、匿名的、可以接受参数和返回值的代码块。

闭包的定义遵循以下语法:

{ [closureParameters -> ] statements }

闭包分为两个部分,分别是参数列表部分[closureParameters -> ]和语句部分statements。 参数列表部分是可选的,如果闭包只有⼀个参数,参数名是可选的,Groovy会隐式指定it作为参数名,如下所示。

{ println it } // 使⽤隐式参数 it 的闭包

当需要指定参数列表时,需要 -> 将参数列表和闭包体相分离。

{ it -> println it } // it 是⼀个显示参数
{ String a, String b -> 
 println "${a} is a ${b}"
} 

闭包是groovy.lang.Closure类的⼀个实例,这使得闭包可以赋值给变量或字段,如下所示。

// 将闭包赋值给⼀个变量
def println ={ it -> println it } 
assert println instanceof Closure
// 将闭包赋值给Closure类型变量
Closure do= { println 'do!' }

闭包既可以当做⽅法来调⽤,也可以显示调⽤call⽅法。

def code = { 123 }
assert code() == 123 // 闭包当做⽅法调⽤
assert code.call() == 123 // 显示调⽤ call ⽅法
def isOddNumber = { int i -> i%2 != 0 } 
assert isOddNumber(3) == true // 调⽤带参数的闭包

闭包作为⽅法的参数

// 闭包作为⽅法的参数
// ⽆参数的闭包
def test1(Closure closure){
 println "test1 start......"
 closure();//调⽤闭包
 println "test1 end......"
}
test1 {println "hahahaha......"}
println("---------------------------");
//有参数的闭包
def test2(Closure closure){
 int a = 100;
 int b = 200;
 println "test1 start......"
 closure(a,b);//调⽤闭包
 println "test1 end......"
}
test2 {x,y->{
 println("x:"+x);
 println("y:"+y);
}}

1.2.6 类

Groovy类⾮常类似于Java类。

def p = new Person()
    p.increaseAge 5
    println p.age
class Person { 
    String name 
    Integer age =10
    def increaseAge(Integer years) {
        this.age += years
    }
}

Groovy类与Java类有以下的区别:

  1. 默认类的修饰符为public
  2. 没有可⻅性修饰符的字段会⾃动⽣成对应的settergetter⽅法。
  3. 类不需要与它的源⽂件有相同的名称,但还是建议采⽤相同的名称。
  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值