Gradle和Groovy介绍
Gradle
- Gradle是一款基于Apache的Ant和Maven概念的项目自动化开源构建工具
- Gradle的核心是基于Java来实现的,可以把Gradle看成就是一个轻量级的Java应用程序
- Gradle使用Groovy、kotlin等语言编写自定义脚本,取代了Apache的Ant和Maven使用xml的方式
Groovy
- Groovy是一种基于JVM的敏捷开发语言
- Groovy代码能够很好的与Java结合,也能扩展现有的代码
Groovy、Java和kotlin三者区别
- Groovy、Java及Kotlin都是基于JVM的开发语言
- Groovy基于Java,在语法上基本相似,但也做了很多自己的扩展
- Goovy 和 Kotlin都有自己支持的DSL,两者有许多共通之处
- Groovy和Java语法非常相似,可以无缝衔接使用Java
项目构建
- 1、通过aapt打包res资源文件,比如AndroidManifest.xml、xml布局文件等,并将这些xml文件编译成二进制,其中assets和raw文件夹的文件不会被编译成二进制,最终会生成R.java和resources.arsc文件。
- 2、aidl工具会将aidl接口转换成对应的java接口
- 3、所有的java代码,包括R.java和Java接口都会被java编译成dex文件
- 4、Dex工具会将上一步生成得.class文件、第三方库和其他.class文件编译生成.dex文件
- 5、上一步编译生成的dex文件、编译过的资源、无需编译的资源(如图片等)会被ApkBuilder工具打包程APK文件
- 6、使用Debug keystore或者Release Keystore对上一步的apk进行签名
- 7、如果对apk正式签名,还需要zipalign工具对apk进行对齐操作,这样应用运行的时候会减少内存的开销
基本语法
Hello Groovy
- 关于idea创建第一个groovy,大家可以 参考这篇文章:https://blog.csdn.net/qq_29860591/article/details/105853214
class Test{
static void main(String[] args) {
println("Hello Groovy")
}
}
语法
- 基本数据类型
- byte、short、int、long、float、double、char、boolean
- 包装类(装箱拆箱)
- String、Byte、Short、Integer、Long、Float、Double、Char、Boolean
- 自动装箱:因为Groovy具有动态类型特性,所以它从一开始就支持自动装箱。实际上,必要时Groovy会自动将基本类型视作对象。
- 字符串
- 单引号字符串是java.lang.String类型,同时不支持插值
- 双引号字符串在没有使用插值表达式情况下是java.lang.String类型, 但如果有插值表达式使用的话,就是groovy.lang.GString类型
- 三引号字符串表示多行的字符串。不必将字符串分割成几块,也不必用连接符或换行符转义字符来将字符串跨行
- 单引号单个字符要表示char类型,需要使用as转换
- ${} 表达式进行插值,去掉花括号不引起歧义的话,可以去掉
- 可以通过+=, -=操作符添加/减少字符 (会自动匹配)
- def:动态类型,使语言能够根据上下文来判定变量类型,类似kotlin的var
- 已使用了final(不可变)、private这样的修饰符的时候,可以省略
class Test{
static void main(String[] args) {
println(A())
}
static def A(){
"Hello Groovy"
}
}
- 数组和列表
- 数组和列表都是使用逗号分割列表的值,使用方括号括起来表示
- Groovy中的数组和列可以随意转换
- def定义的变量会自动推断 [ ] 类型是列表
- Groovy列表是普通的JDK java.util.List,因为Groovy中没有定义自己的集合类
- ?.实现安全操作符
class Test{
static void main(String[] args) {
println(test("niamkaep"))
println(test(null))
}
static def test(str){
str?.reverse()
}
}
- 范围
范围是一种特殊的列表,由序列中的第一个和最后一个值表示,Range可以是包含或排除。包含范围包括从第一个到最后一个的所有值,而独占范围包括除最后一个之外的所有值。也可以使用表达式来表示范围,例如:
- 1..10 包含范围的示例;相当于[0,10]
- 1..<10 独占范围的示例 (开区间);相当于[0,10)
- 'a'..'z' 范围也可以由字符组成;
- 10..1 范围也可以按降序排列;
- 'z'..'a' 范围也可以由字符组成并按降序排列
class Test{
static void main(String[] args) {
( 'z'..'a' ).forEach({
print(it+"\t")
})
}
}
- 映射
- 映射(也称为关联数组,字典,表和散列)是对象引用的无序集合。
- Map集合中的元素由键值访问。Map中使用的键可以是任何类,如果不能推断具体key类型,默认就是字符串。
- 在Groovy中可以使用特定的表述方式来指定映射:
- [k1:v1,k2:v2] 具有键值对的集合。
- [:] 空映射
class Test{
static void main(String[] args) {
def map=[a:1,b:444]
map.forEach{k,v->
println("key=${k.class}")
}
}
}
- 运算符及控制语句
- Groovy支持运算符重载
- 循环语句
- 除了和Java保持差不多的用法外,还支持结合范围的用来进行循环
- 组合闭包来实现更简化的循环操作
- 条件语句
- 除了和Java保持差不多的用法外,还多了Groovy的一些扩展
- 可以组合闭包实现更灵活的条件语句
方法
getter/setter
- 默认会生成getter, setter方法:
- 并且可以直接像使用成员变量的方法来自动判断调用getter/setter。
- 当进行赋值时调用setter方法,
- 当直接访问值时调用的是getter方法。
- 使用'.@'才是真正的直接访问变量,跳过默认的getter/setter方法调用
class Person{
private def name="peakmain"
private def getName() {
println("getName")
return name
}
}
class Test{
static void main(String[] args) {
def person = new Person()
println(person.@name)
}
}
private
- 所有的变量默认是public
- 如果要设置为私有禁止直接访问,仅仅设置private无用,放在另一个package也不行
- 重载这个变量的getter/setter方法,并且再调用方法时抛出异常
class Person{
private def name="peakmain"
private def getName() {
throw new IllegalAccessException("can not get")
return name
}
}
class Test{
static void main(String[] args) {
def person = new Person()
println(person.name)
}
}
- Java中如果没有显式的指定访问修饰符(public、protected、private)那么默认是包访问权限,Groovy使用@PackageScope
构造方法
- 构造方法重载规则跟Java一样。
- 如果没有指定具体参数的类型时,默认推断类型是Object。
- 在构造方法中传入具名参数,但是要注意:传入的参数都是键值对,实则就是一个Map类型!
- 这种方式传入的参数会自动拆解Map并且调用setter方法对应的进行赋值。
- 优先是当成Map匹配构造方法,如果匹配不到则调用无参的构造方法
class Person{
def name
def age
}
class Test{
static void main(String[] args) {
def person = new Person(name: "123", age: 123)
println(person.name)
}
}
- 如果参数中还有非键值对的传参,就会把这些键值对当成Map了不会再进行自动拆解赋值。所以要有对应的构造方法才行。
闭包
- Groovy中可以理解为闭包就是可执行的代码块,或匿名函数。闭包在使用上与函数与许多共通之处,但是闭包可以作为一个函数的参数
- 默认情况下,闭包能接收一个参数,且参数字段默认使用it
class Test {
static def Person = {
println(it)
}
static void main(String[] args) {
Person(111)
}
}
- 在箭头前面没有定义参数,这时候闭包不能传入参数
- 可以定义多个接收的参数
- 使用参数默认值,跟方法使用规则一样
闭包与接口/类进行转换
- 即使定义的方法传入的是闭包,但是如果传入的对象的类型也有call方法,那么,是可以执行这个对象的call方法的,实际上,闭包执行的也是call方法。
- 在一个对象上调用(),表示调用这个对象的call方法
interface Action {
void call()
}
static void func(closure) {
closure()
}
static void main(String[] args) {
func(new Action(){
@Override
void call() {
println("测试")
}
})
}
闭包重要的参数
- private Object delegate;
默认就是owner,但是代理可以修改 - private Object owner;
定义它的时候的类的对象 - private Object thisObject;
- private int resolveStrategy;
闭包参数的优先级 - protected Class[] parameterTypes;
闭包的参数类型 - protected int maximumNumberOfParameters;
参数类型的个数
代理策略
class Test {
def func() {
println("func")
}
static def clouse = {
func()
}
static void main(String[] args) {
clouse.delegate = new Test()
clouse()
}
}
- groovy.lang.Closure#DELEGATE_FIRST
delegate优先 - groovy.lang.Closure#DELEGATE_ONLY
只在delegate中找 - groovy.lang.Closure#OWNER_FIRST
owner优先 - groovy.lang.Closure#OWNER_ONLY
只在owner找 - groovy.lang.Closure#TO_SELF
只在自身找(闭包内部),意义不大