Android Gradle—了解Gradle及自动化构建

4,692 阅读7分钟

小知识,大挑战!本文正在参与“  程序员必备小知识  ”创作活动

本文同时参与 「掘力星计划」  ,赢取创作大礼包,挑战创作激励金

前言

本专栏内容主要分为两大部分:

  1. Groovy基础到进阶
  2. Gradle开发及Gradle在Android中的使用。

本专栏内容尽量做到覆盖全满,不遗漏知识点。

  1. 对于Groovy的学习会基于已掌握的Java及Kotlin语言,通过对比分析来提高学习效率。
  2. 对于Gradle的内容我们主要针对在Android开发中的实际使用来进行讲解,做到学以致用的目的。

1. Gradle介绍

  • Gradle是一款基于Apache的Ant和Maven概念的项目自动化开源构建工具。Gradle的核心是基于Java来实现的,可以把Gradle看成就是一个轻量级的Java应用程序。
  • Gradle是使用Groovy、Kotlin等语言编写自定义脚本,取代了Ant和Maven使用xml配置文件的方式,很大程度简化了开发时对项目构建要做的配置,使用更加灵活和强大。

1.1 为什么要学习Gradle

Gradle不仅是目前Andorid最主流的构建工具。而且不少技术领域如组件化、插件化、热修复,及构建系统 (很多优秀的框架都是在编译时或者打包之前做一些特殊的处理) ,都需要通过Gradle来实现,不懂Gradle将无法完成上述事情,所以学习Gradle非常必要。

1.2 关于项目构建

  1. 对于Java应用程序,编写好的Java代码需要编译成.class文件才能够执行。所以任何的Java应用开发,最终都需要经过这一步;
  2. 编译好了这些class文件,还需要对其进行打包。打包不仅针对于这些class文件,还有所有的资源文件等。比如web工程打包成jar包或者war包就包含了自己的资源文件,然后放到服务器上运行。
  3. Andorid工程编译好的class文件还要被打包到dex包中,并且所有的资源文件进行合并处理,甚至还需要对最终打包出来的文件进行加密和签名处理等等。

图解说明

图片1.png

1.3 自动化构建工具的发展

  1. “石器时代”:自己编写命令脚本,进行编译和打包
  2. “蒸汽时代”:Make、Ant工具的出现
  3. “电气时代”:Maven
  4. “信息时代”:Gradle,更高级的自动构建工具出现 ...

1.4 Gradle提供了什么

  • 对多工程的构建支持非常出色,尤其是工程依赖问题,并支持局部构建;
  • 多种方式的依赖管理:如远程Maven仓库,nexus私服,ivy仓库或者本地文件系统等;
  • 支持传递性依赖管理;
  • 轻松迁移项目工程;
  • 基于Groovy等语言构建脚本,简便且灵活;
  • 免费开源,并且整体设计是以作为一种语言为导向的,而非成为一个严格死板的框架。

上面我们提到, Gradle是使用Groovy、Kotlin等语言编写自定义脚本,现在我们了解了Gradle相关的,接下来将介绍 Groovy。

2. Groovy介绍

Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy代码能够与Java代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy也可以使用其它非Java语言编写的库。

这里我们提到,Groovy代码能够与Java代码很好地结合,然后现在Android开发也慢慢往 Kotlin 发展,那么我们看看这三者的区别。

2.1 Groovy & Java & Kotlin

  • Groovy、Java及Kotlin都是基于JVM的开发语言;
  • Groovy基于Java,在语法上基本相似,但也做了很多自己的扩展。Groovy除了可以面向对象编程,还可以用作纯粹的脚本语言,这一点和Kotlin是一样的;
  • Goovy 和 Kotlin都有自己支持的DSL,两者有许多共通之处。

这里有一组比较有意思的对话:

Groovy:我不是针对Java,而是所有不能愉快写DSL的都是laji。
Clojure:我真的不是针对Java,只是关于并发,我有一个大胆的想法。
Scala:我也真的不是针对Java,只是关于并发,我还有一种大胆的想法。
Kotlin:我就是处处针对Java!
Java退出了群聊...

满满感受到Java的无奈 :》

2.2 Groovy特性

  • 同时支持静态类型和动态类型;
  • 支持运算符重载;
  • 支持DSL语法特性;
  • 本地语法列表和关联数组;
  • 各种标记语言,如XML和HTML原生支持;
  • 对正则表达式的本地支持;
  • Groovy和Java语法非常相似,可以无缝衔接使用Java;
  • 支持使用现有的Java库,并做了一定的扩展。

这里说到,Groovy和Java语法非常相似,可以无缝衔接使用Java,那我们来看看是如何无缝衔接的。

3. 从Java到Groovy

注:开发环境为:Idea+Groovy环境,所以开发者需要额外在Idea编译器里面配置Groovy环境(点击查看如何配置Groovy环境)

2.png

如图所示

创建项目时选择Groovy选项,可以不用勾选Kotlin环境直接创建,毕竟要看如何从Java到Groovy。这里分别举几个比较常用的例子。

3.1 对应第一个项目

class HelloGroovy {
    static void main(String[] args) {
        System.out.println("hello Groovy!");
    }
}

这是很标准的第一项java项目。接下来我们看看 Groovy 的第一个项目

def test() {
    "hello Groovy!" //方法返回值不用写return,已最后一句话代码作为方法的返回类型
}

println(test()) //代码末尾可以省略 分号

println test() //打印甚至还能省略外面的一对大括号。

接下来看看我们经常用的循环:

3.2 对应的循环

class HelloGroovy {
    static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.print(i+"\t ha")
        }
//        System.out.println("hello Groovy!")
    }
}

这里不用多说了,java大家都熟悉。现在看看Groovy的语法。

3.times {
    println it+"\t haha"
}

或者

(0..2).forEach{
    println it+"\t haha"
}

运行效果

0	 haha
1	 haha
2	 haha

熟悉Kotlin的小伙伴应该能够秒懂这段代码,毕竟 kotlin 是在 groovy基础上进阶改良的,所以作为 Kotlin的前辈,语法几乎都是类似的。

3.3 对应的安全操作符

我们就以最经典的非空判断为准。

class HelloGroovy {

    static String toUpperCase(String content) {
        if (content == null || content.length() == 0) {
             return "null";
        }
        content = content.toUpperCase();
        return content;
    }

    static void main(String[] args) {
        String content = "abc";
        System.out.println(toUpperCase(content));
    }

}

这里很经典的非空判断,不为空就转大写。接下来看看Groovy对应的

def toUpperCase(str) {
    str?.toUpperCase()
}

println toUpperCase("abc")
println toUpperCase(null)

Groovy运行效果

ABC
null

学过Kotlin的小伙伴都知道,Kotlin代码自带非空检测,只要可能为空的部分就必须让开发者处理,否则连编译都不能通过。要想通过编译,要么处理为永不为空,要么调用前加一个问号,表示为空就不执行。这里的 Groovy 语法和Kotlin 一样。

3.4 数据类型

在开发中我们定义对应的变量,肯定离不开对应的数据类型。在我们熟悉的Java中,我们所使用的基本数据类型都会有装箱拆箱的操作,比如说。

  • 基本数据类型

    byte、short、int、long、float、double、char、boolean

  • 包装类(装箱、拆箱)

    String、Byte、Short、Integer、Long、Float、Double、Char、Boolean

而在Groovy中,因为它具有动态类的特性,所以它从一开始就支持自动装箱实际上,必要时Groovy会自动将基本类型视作对象

3.5 字符串

Java大家都再熟悉不过了,后面就直接开始贴Groovy的代码。

def name = 'carName'
def realName = "$name:AAAA"
println name.getClass()
println realName.getClass()
def string='''
carName
is
$name
'''
println string

运行效果

class java.lang.String
class org.codehaus.groovy.runtime.GStringImpl

carName
is
$name


Process finished with exit code 0

从这里可以看出:

  • 单引号字符串是java.lang.String类型,同时不支持插值
  • 双引号字符串在没有使用插值表达式情况下是java.lang.String类型, 但如果有插值表达式使用的话,就是groovy.lang.GString类型
  • 三引号字符串表示多行的字符串。不必将字符串分割成几块,也不必用连接符或换行符转义字符来将字符串跨行

3.6 数组和列表

def array = ["1", "2", 3]
println array.getClass()
// int []
String[] array2 = ["1",new Object(),2, "3"]
//def array2 = [1, 2, 3] as int[]
println array2.getClass()

println array2[1].toString()
println array2[1].getClass()

可以看出,这里定义了一个集合和一个数组,在集合和数组里面,我故意放入了不同类型的数据,代码也没有报错,我们运行看看效果。

class java.util.ArrayList
class [Ljava.lang.String;
java.lang.Object@3b4ef7
class java.lang.String

由此我们可得:

  • 数组和列表都是使用逗号分割列表的值,使用方括号括起来表示
  • Groovy中的数组和列可以随意转换
  • def定义的变量会自动推断 [ ] 类型是列表
  • Groovy列表是普通的JDK java.util.List,因为Groovy中没有定义自己的集合类

3.7 范围

范围是一种特殊的列表,由序列中的第一个和最后一个值表示,Range可以是包含或排除。包含范围包括从第一个到最后一个的所有值,而独占范围包括除最后一个之外的所有值。

(0..2).forEach{
    println it+"\t haha"
}
('a'..<'d').forEach{
    println it
}

def range = 0..10
println range.getClass()

运行效果

0	 haha
1	 haha
2	 haha
a
b
c
class groovy.lang.IntRange
Process finished with exit code 0

由此我们可得:

  • 1..10 包含范围的示例
  • 1..<10 独占范围的示例 (开区间)

3.8 映射

映射(也称为关联数组,字典,表和散列)是对象引用的无序集合。Map集合中的元素由键值访问。Map中使用的键可以是任何类,如果不能推断具体key类型,默认就是字符串。

在Groovy中可以使用特定的表述方式来指定映射

// [k1:v1,k2:v2]
def map = [a: 11, b: 12]
map.forEach { k, v ->
    println "key=${k.class} , value=$v"
}

def value = map['a']
println value

运行效果

key=class java.lang.String , value=11
key=class java.lang.String , value=12
11

由此我们可得:[k1:v1,k2:v2] 具有键值对的集合。

4. 结束语

到这,这篇文章差不多结束了,相信看到这里,你应该大致了解了Gradle及自动化构建对应的发展和作用以及Groovy的基本语法。在下一篇中将会重点讲解Groovy的类与方法

欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边