携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>
🔥 Hi,我是小余。
本文已收录到 GitHub · Androider-Planet 中。这里有 Android 进阶成长知识体系,关注公众号 [小余的自习室] ,在成功的路上不迷路!
前言:
大家回想一下自己第一次接触Gradle
是什么时候?
相信大家也都是和我一样,在我们打开第一个AS项目的时候,
发现有很多带gradle字样的文件:setting.gradle, build.gradle,gradle.warpper
,以及在gradle
文件中各种配置,
这些都是啥wy啊。。
特别对于一些小公司开发人员,因为接触架构层面的机会很少,可能在使用AS几年后都不一定对Gradle
有太多深入了解,这是实话,因为笔者就是这么过来的。。
而Gradle
又是进阶高级
开发的必经之路。
好了,接下来进入正题,此系列笔者会由浅入深的方式,带领大家来了解下,Gradle
背后究竟有哪些奥秘。
本系列文章:
Gradle筑基篇:
- Gradle筑基篇(一)-初识Gradle
- Gradle筑基篇(二)-Groovy语法的详解
- Gradle筑基篇(三)-Gradle生命周期
- Gradle筑基篇(四)-Gradle APi详解
- Gradle筑基篇(五)-Gradle自定义插件
- Gradle筑基篇(六)-Gradle Maven仓库管理
Gradle进阶篇
- Gradle进阶篇(六)-AGP详解
本篇是这个系列的第二篇文章:groovy语法详解
Gradle
定义:
很多开发喜欢把Gradle
简单定义为一种构建工具,和ant,maven
等作用类似,
诚然Gradle确实是用来做构建,但是如果简单得把Gradle拿来做构建,就太小看Gradle了.
笔者更愿意将Gradle看做一种编程框架
。在这个框架中,你可以做很多ant,maven等常用构建工具做不了的事情,
如将自己的任务task集成到构建生命周期中,完成文件拷贝,脚本编写等操作。
Gradle
优缺点:
相较早期的构建工具:ant,maven等。
优点如下:
- 1.使用DSL Grovvy语言来编写::了解ant的同学应该都知道:ant使用的是xml配置的模式,而Gradle使用的是
表达性的Groovy
来编写,
Groovy同时支持面向对象和面向过程
进行开发,这个特性让Groovy
可以写出一些脚本的任务,这在传统ant,maven上是不可能实现的 - 2.基于java虚拟机::
Groovy
是基于jvm
的语言,groovy
文件编译后其实就是class文件,和我们的java
一样。
所以在gradle构建过程中,我们完全可以使用java/kotlin去编写我们的构建任务以及脚本,极大的降低我们学习的成本。
- 3.Gradle自定义task:可以构建自己的任务,然后挂接到gradle构建
生命周期
中去,这在ant,maven上也是不可能实现的, - 4.扩展性好:gradle将关键配置扔给我们开发者,开发者配置好任务后,无需关心gradle是如何构建的。
缺点:
用过gradle都知道,低版本gradle的项目在高版本的gradle中经常出现很多莫名其妙的错误,
向后兼容性较差
。
介绍了那么多,下面正式来讲解今天的主角:Groovy
Groovy
语法详解
因为我们的Groovy和java很类似,所以这里我们以和java的差异性进行展开,这样可以更好的去理解groovy语法
1.编程方式
java
:面向对象
groovy
:面向对象和过程
groovy不仅可以和java一样面向对象进程编程,也可以创建面向过程的脚本开发:
1 | java复制代码package variable |
2.语法简洁
- 2.1:
分号
:groovy默认行尾不加分号 - 2.2:
public
:默认属性为public,而我们的java是protected - 2.3:
setter/getter
:groovy默认给我们类内部属性,创建setter和getter方法,外部只需要使用属性名访问即可 - 2.4:
字符串
:groovy支持三种类型的字符串表达式定义
+ `单引号`:不能使用+号代替,如果你确定这个字符串只是使用,不会更改那么你可以这么定义
1
2
3
4
java复制代码//单引号定义不可更改内容
def s1 = 's1'
//使用转移字符://s'a'2
def s2 = 's\'a\'2'
+ `双引号`:
在字符串内部可以使用${}引用外部元素,这个外部元素可以是任何属性或者操作方法
1
java复制代码def s6 = "2+3 is ${2+3}"
+ 三引号:支持自动换行
一般我们会使用前两种,最后一种很少用
- 2.5:使用弱声明:
def
,编译过程会自动类型检测,这个属性和kotlin的val/var
很像。
1 | java复制代码def str = "this is groovy str" |
3.方法
3.1: 方法定义
groovy中:使用def声明方法的返回值,如果没有返回值,则默认返回一个null
1 | java复制代码def echo(){ |
3.2:方法参数:
groovy传入的参数可以省略参数类型,且可以设置参数默认值,有默认值调用的时候可以省略带默认值的参数
1 | java复制代码def echo(message,name = '123'){ |
3.3:方法返回值
使用return返回,如果省略return,则返回的是最后方法最后一行
1 | java复制代码def echo(){ |
3.4:方法调用流程
groovy方法调用不像我们java,其内部给我们创建了很多判断的分支,支持在运行期动态添加方法
下面是groovy方法调用流程图:
- 3.4.1:
invokeMethod
:对于类中所有调用方法:包括已定义和未定义方法,都会走到这个invokeMethod方法中,需要实现:GroovyInterceptable
接口
这个方法可以在我们方法执行器做一些方法类型参数等判断
1 | java复制代码class Person implements GroovyInterceptable{ |
可以看到所有的方法都被分派到invokeMethod且没有执行后续流程:这个和我们java运行期动态代理模式
有点类似,我们可以在invokeMethod
中实现一些AOP
的架构,如打印所有方法的统一日志
等。
- 3.4.2:
methodMissing
:对于未定义的方法,如果重写这个methodMissing,则会调用这个方法
1 | java复制代码Object methodMissing(String name, Object args) { |
最新版本groovy未发现这个方法,应该是被去掉了。不过这个对于我们开发关系不大
- 3.4.3:
元编程metaClass
:可以在运行期注入属性和方法包括静态方法,这个特性就比较厉害了,对于一些第三方类库,可以使用这个方式在运行期动态创建方法,相当于对类库进行了一次扩展
学习过kotlin的都知道:扩展函数和扩展属性,差不多是这个用法
1 | java复制代码注入属性: |
4.集合
4.1:集合分类
groovy中集合有三种:
列表List
:对应java中的List
1 | java复制代码 def list = [1, 2, 3, 4,5,6] |
映射Map
:对应java中的Map
1 | java复制代码 def map = [key1:'value',key2:'value2'] |
注意:map中的key默认都是String类型的字符串,即使我们自己没加,编译器也会给我们加上
范围Range
:groovy中独有
1 | java复制代码def range = [1..100] |
range其实就是指定了一个list的范围,而不需要一个一个列出来
如下使用:
1 | java复制代码/******switch case*****/ |
4.2:集合遍历
所有集合都可以使用each
和eachWithIndex
进行遍历,当然也可以使用java中的for循环,但在groovy中一般不这么用
1 | java复制代码class Stu{ |
4.3:查找
groovy中查找提供了find
和findAll
方法,用法如下:
1 | java复制代码//find查找一项 |
4.4:分组:
使用groupBy
关键字
1 | java复制代码def group = students.groupBy { |
4.5:排序:
使用sort
1 | java复制代码def sort = students.sort {student1,student2 -> |
5.闭包
闭包在我们groovy
中起着很大比重,如果想要学好groovy
,闭包一定得掌握好,
在我们build.gradle
其实就有很多闭包使用:
如:
1 | java复制代码android{ |
这里面的android {}
其实就是一个闭包结构,其内部的sourceSets{}
又是闭包中的闭包,可以看到闭包在我们的gradle
中无处不在.
学好闭包真的很关键
常用闭包方式:
1 | java复制代码{'abc'} |
5.1:闭包的定义及基本方法
闭包概念
:其实就是一段代码段,你把闭包想象为java中的回调Callback
即可,
闭包在Groovy
中是groovy.lang.Closure
的实例,可以直接赋值给其他变量.闭包的调用
:
1 | java复制代码def closer = {1234} |
闭包参数
:带参数的闭包 使用 -> 如果是一个参数可以直接使用it代替和kotlin中的lambda类型类似
1 | java复制代码def closerParam = { name,age -> |
闭包返回值
:闭包返回值 如果没有定义return则直接返回最后一句话的返回值
1 | java复制代码println result //打印结果:return hei |
5.2:闭包使用详解
- 5.2.1:与
基本类型
结合使用:
1 | java复制代码//upto:实现阶乘 |
- 5.2.2:与
String
结合使用
1 | java复制代码String str = "the 2 and 3 is 5" |
- 5.2.3:与
数据结构
结合使用:
这部分操作和与String结合使用类似,不再讲解 - 5.2.4:与
文件
结合使用
这部分在讲解到文件操作的时候,再进行具体讲解
5.3:闭包进阶详解
- 5.3.1:闭包关键变量:
this,owner,delegate
情况1
:一般情况:
1 | java复制代码def scriptCloser = { |
可以看到一般情况下:三种都是相等的:都代表当前闭包对象
情况2
:我们来看下面的情况:闭包中有闭包
1 | java复制代码def nestClosure = { |
看到在闭包中调用闭包:
this还是执行外部的Closer对象,而
owner
和delegate
变为了Closer
的内部闭包对象
情况3
:最后来看一种情况:使用delegate委托
1 | java复制代码class Student{ |
通过上面三种情况:
总结出:
this
:指向最外部的Closer对象owner
:执行当前闭包的Closer对象,特指当前,所以对闭包中的闭包,指向内部的闭包delegate
:这个是闭包的代理对象,如果有单独配置这个delegate,且设置了委托策略 =DELEGATE_FIRST
, 则闭包中的所有内部属性都会优先使用delegate中的对象
下面我们就来讲解闭包的委托策略
- 5.3.2:闭包
委托策略
闭包中给我提供了以下策略:
1 | java复制代码//优先使用ower中的属性 |
通过5.3.1中的例子,我们也可以看出Groovy默认使用的是OWNER_FIRST的委托策略
6.文件
groovy文件操作完全兼容java的文件操作,但groovy集成了自己的高阶使用方式
- 读文件:
withReader
1 | java复制代码def file = new File('../../hello_groovy.iml') |
- 写文件:
withWriter
1 | java复制代码//写文件:withWriter:实现文件拷贝操作 |
- 读对象:
withObjectInputStream readObject
Groovy不仅可以写文件,还可以写入和读取对象操作
1 | java复制代码//读对象 |
- 写对象:
withObjectOutputStream writeObject
1 | java复制代码//写对象: |
7.Json
- 7.1:Object转Json字符串转
1 | java复制代码//1.Object 转JSon |
- 7.2:Json字符串转Object
1 | java复制代码//2.JSon转Object |
从网络获取Json数据操作:
这里引入OkHttp
1 | java复制代码def getNetWork(String url){ |
8.XML
java中处理xml:使用的一般是dom文档驱动处理或者sax事件驱动处理
groovy处理xml
:
- 8.1:groovy中如何解析xml:
使用XmlSlurper进行解析
1 | java复制代码final String xml = ''' |
- 8.2:
xml节点遍历
深度遍历
:遍历所有的李刚的书名
1 | java复制代码def depFirst = response.depthFirst().findAll { book -> |
广度遍历
1 | java复制代码def name1 = response.value.books.children().findAll { node -> |
- 8.3:
groovy中如何创建一个xml
:使用MarkupBuilder
需求:生成xml格式数据
1 | java复制代码/** |
查看文件release.xml
1 | java复制代码<langs type='current' count='3' mainstream='true'> |
9.Groovy实战:
下面我用一个Groovy实战项目来总结前面所讲的内容:
项目需求:从网络上获取当前版本信息,然后使用groovy脚本将获取到的版本信息写入到本地文件中
- 1.
groovy环境搭建
下载最新版本的Intellij IDEA
:笔者使用的版本:20220103
版本 - 2.
创建groovy工程
:
- 3.
添加OkHttp网络请求库
这里我们为了方便,使用了我们android中常用的网络请求库OkHttp
- 4.
完整代码
如下:
1 | java复制代码package var |
这里结合我们前面讲解的关于文件操作,xml和json等数据格式操作,从网络上读取json数据,写入xml格式到我们本地项目的路径,大家可以根据我们前面所讲自己去实现一个类似的逻辑,多动手,相信你对groovy会有更深的理解。
总结:
本篇主要讲解了我们使用groovy
语言的基本用法,因为也是基于jvm
的语言,对于有java
基础的同学学起来应该会很轻松
后面会继续讲解其他关于Gradle
的关键知识,敬请期待。。
本文转载自: 掘金