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

项目构建

Gradle基础到进阶——基本语法、方法和闭包(一)_Groovy

image.png

  • 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


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类型


image.png

  • 三引号字符串表示多行的字符串。不必将字符串分割成几块,也不必用连接符或换行符转义字符来将字符串跨行
  • 单引号单个字符要表示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中没有定义自己的集合类


image.png


Gradle基础到进阶——基本语法、方法和闭包(一)_Groovy_02

image.png

  • ?.实现安全操作符


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;
    参数类型的个数


image.png

代理策略


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
    只在自身找(闭包内部),意义不大