Gradle学习系列(一):Groovy学习

概述

又开始了一个新的系列,这个系列学习Gradle,目标就是彻底理解Gradle,主要还是做下自己理解的笔记,防止忘记

Gradle系列(一):Groovy学习

配置Groovy环境

我这里用的是Mac,所以简单介绍下mac怎么配置Groovy环境,由于Groovy是运行在java虚拟机上的,所以首先要确定你的电脑有java环境

  • 首先去这个地址下载Groovy http://www.groovy-lang.org/download.html

  • 然后把下载下来的压缩包,解压到你需要的位置

  • 最后修改.bash_profile文件


vi ~/.bash_profile

将下面的语句添加进去

export PATH=$PATH:/Users/***/Documents/groovy-2.4.12/bin

然后终端输入

source ~/.bash_profile
groovy -v

看到groovy的版本号表示已经配置环境完成了

然后用VscodeCode创建一个hello.groovy的文件,内容如下:

class Example {
    
    
   static void main(String[] args) {
    
    
        // 使用 println 打印信息到 stdout
        /*除了上面的注释方法外,这里没也是注释信息哦*/
        println '测试数据'
        println "Hello World";
   }
}

运行这个文件

这样就是就算完成了环境的配置

Groovy 语法学习

一些需要提前了解的知识

  • Groovy 的注释和java一样 // 或者/**/
  • Groovy语句可以不用分号结尾,这个其实是为了代码写起来更加简洁
  • Groovy中支持动态类型,就是定义变量的时候可以不定义类型,Groovy中定义变量可以使用def关键字,虽然def不是必须的,但是还是建议使用def,让代码更加清晰
def variable1 = 1 //可以不使用分号结尾
def varable2 = "I am a person"
def int x = 1 //变量定义时,也可以直接指定类型
  • 函数定义时,参数的类型也可以不指定
String testFunction(arg1,arg2){
    
    //无需指定参数类型 ...
}
  • 除了定义变量不指定类型外,Groovy中函数的返回值也可以是无类型的
//无类型的函数定义,必须使用 def 关键字 
def nonReturnTypeFunc(){
    
    
last_line //最后一行代码的执行结果就是本函数的返回值 
}

//如果指定了函数返回类型,则可不必加 def 关键字来定义函数 
String getString(){
    
    
return "I am a string" 
}
  • 函数返回值:Groovy的函数里,可以不使用ruturn,如果不使用return的话,那么函数中最后一句代码执行结果设置为返回值
//下面这个函数的返回值是字符串"getSomething return value" 
def getSomething(){
    
    
"getSomething return value" //如果这是最后一行代码,则返回类型为 String
1000 //如果这是最后一行代码,则返回类型为 Integer 
}

如果函数指明了返回值的类型,那么就必须返回正确的类型,否则就报错,如果返回值是动态类型,才可以返回任意数据类型

  • Groovy对字符串支持很强大
1 单引号''中的内容严格对应 Java 中的 String,不对$符号进行转义
def singleQuote='I am $ dolloar' //输出就是 I am $ dolloar

2 双引号""的内容则和脚本语言的处理有点像,如果字符中有$号的话,则它会$表达式先求值。
def doubleQuoteWithoutDollar = "I am one dollar" //输出 I am one dollar
def x = 1
def doubleQuoteWithDollar = "I am $x dolloar" //输出 I am 1 dolloar

3 三个引号'''xxx'''中的字符串支持随意换行 比如 
def multieLines = ''' begin
line 1 
line 2 
end '''
  • 最后除了每行代码不用加分号外,Groovy中函数调用的时候还可以不加括号
println("test") ---> println "test"

注意:虽然写代码的时候可以函数调用不带括号,但是函数调用如果是Groovy的API那么可以不带括号,如:print方法,否则还是需要带括号的,因为Groovy对此的支持还是有一些问题的

Groovy中的数据类型

这里我们只介绍和java中不太一样的东西

基本数据类型

作为动态语言,Groovy中所有的事物都是对象,所以int,boolean这些java中的基本数据类型,在Groovy中其实对应的是他们包装数据类型,比如 int - integer,boolean-Boolean

容器类

Groovy中容器其实就三种

  • List:链表,其底层对应java中的List接口,一般用ArrayList作为实现类
  • Map:键-值表,其底层对应java中的LinkedHashMap
  • Range:范围,他其实是List的一种扩展

List

class Example {
    
    
   static void main(String[] args) {
    
    
       //定义list,可以是任何类型的元素
        def list  = [2,"吃",true]
        //list元素赋值,不用担心数组越界,如果超过长度list会自动向该索引填充
        list[4]="tt"
        //遍历list
        for (a in list) {
    
    
            println a;
        }
   }
}

Map

Map由[:]定义,冒号左边是key,右边是value,key必须是字符串,value可以是任何的对象,key可以加’’,也可以不加,比如 def map = [key1: "测试",key2: true];这样系统会自动处理成字符串 ‘key’,‘key’

class Example {
    
    
   static void main(String[] args) {
    
    
       //定义map
      def map = ['key1': "测试",'key2': true];
      //访问map中的值
      println map.key2;
      println map['key1'];
      //定义新的map的key
      map.anotherkey = "another";
      println map.anotherkey;
   }
}

看下输出

$ groovy map.groovy 
true
测试
another

如果不加’'的话,map的key和变量同名怎么办呢?看下面例子,也就是说直接使用aa就是简单的字符串,如果需要取变量的值需要用(aa)的方式取

      def aa  ="测试";
      def map1 = [aa:"11",(aa):22];
      println map1.aa;
      println map1."测试";

输出

11
22

Range类

Range类是对List的一种扩展

class Text{
    
    
      static void main(String[] args) {
    
    
          //包含12345
          def range  = 1..5;
          println range.from;
          println range.to;

          //包含1234个元素
          def range1 = 1..<5;
           println range1.from;
          println range1.to;
   }
}

查看Groovy API技巧

真正写代码的是时候还是要查看 Groovy SDK API的,因为我们不可能记住全部的用法吧

Groovy API文档的地址 http://www.groovy-lang.org/api.html

我们以上面的Range为例,首先需要定位到Range类

然后在API文档查找你需要的使用的函数和属性就行,但是我们发现,这个文档里面并没有,上面使用的from和to属性的介绍,这是为什么?

我们发现索然没有 from/to属性的介绍,但是却有 getFrom 和 getTo 这俩个函数

原来根据Groovy的规则,假如文件有个 xx 的成员变量,Groovy会自动为他添加 getXx()和setXx()俩个函数,所以当我们看到Range中有getFrom和getTo的时候,我们就可以确定Range中有from和to属性

闭包

什么是闭包

闭包英语是Cloure,是Groovy中非常重要的数据类型,他代表了一段可执行代码,如下:

class Example {
    
    
   static void main(String[] args) {
    
    
      def closure = {
    
    //闭包是一段代码,所以用花括号圈起来
          String param1,int param2->//箭头前面是参数,后面是代码
          println param1+param2;//这个是代码
        
          //最后一句是返回值,也可以用return,和Groovy函数用法一样
          '返回值'
      }

      def aa =  closure("测试",11);
      closure.call("你好",22);

      println aa;
   }
}

看下输出

测试11
你好22
返回值

也就是说,闭包的格式是

def xxx = {
    
    paramters -> code} //或者
def xxx = {
    
    无参数,纯 code} 这种 case 不需要->符号

调用闭包

闭包对象.call(参数) 
或者: 闭包对象(参数)

这就是闭包的定义和使用,还需要注意一点

如果闭包没有定义参数的话,那就会有一个隐藏参数,这个参数的名字是it,和this的作用相似,it代表闭包的参数

      def closure1 ={
    
     println "hello,$it"}

      closure1("小明");

      def closure2 ={
    
    it->println "hello,$it"}
      closure2("小红")
   }

上面的写法等同于下面写法,看下输出

hello,小明
hello,小红

但是如果闭包中是这种写法,则表示闭包没有参数

      def closure3 = {
    
    -> println "text"}

这种写法就不能传参数了,传了的话就会报错

闭包使用需要主要的点

省略圆括号

有些函数最后一个参数是闭包,比如下面:

public static <T> List<T> each(List<T> self, Closure closure)

上面这个函数表示针对List的每一个元素,都会送入闭包做些处理,那该如何使用这个函数呢?

class Example {
    
    
   static void main(String[] args) {
    
    
       //定义list,可以是任何类型的元素
        def list  = [2,"吃",true]
         list.each{
    
    
          println it
      }
   }
}

上面代码有俩个知识点

  • each函数调用的圆括号省略了,在Groovy中当函数的最后一个参数是闭包的话,就可以省略圆括号,比如:
 static def text(int a ,String b,Closure closure){
    
    
     def aa  = a + b;
     closure(aa);
 }

调用text方法

  //第一种调用
  text(1,'测试',{
    
    
          println it;
      })
	  //第二种调用
      text 2,'你好',{
    
    
          println it;
      }
   }

打印结果

1测试
2你好

可以看到上面俩种调用方式,他们的差别就是调用少了括号

这种形式在android中还是很常见的,比如:

dependencies {
    
    
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

比如这些其实就是闭包的写法,dependencies其实就是一个函数

void dependencies(Closure configureClosure);

这种方式虽然写起来方便,一开始阅读起来还是挺令人困惑的,要花些时间熟悉下

如何确定闭包的参数

还有另一事情比较令人困惑,那就是如何确定闭包的参数,比如刚才的each方法

public static <T> List<T> each(List<T> self, Closure closure)

看到函数,我们只知道要传入一个闭包,但是参数是什么,返回值是什么?

所以说闭包虽然很方便,但是它和使用它的上下文关联性很强,那么我们到底该怎么确定他的参数和返回值呢?
解决方式只能去看文档

文档介绍的是遍历List,将每个元素传递给给定的闭包。所以这个闭包只有一个参数,就是遍历的元素

所以闭包的使用还是很坑的,很大程度依赖你对API的熟悉程度,所以在最开始,对API的查询是少不了的

脚本类

Groovy可以向java一样,引入其他包的类,比如我在文件夹 com.aa中创建文件Aa.groovy

package com.aa
class Aa{
    
    
    String a;
    String b;

    Aa(String a,String b){
    
    
        this.a=a;
        this.b=b;
    }

    def print(){
    
    
        println a+b;
    }
}

这个类其实和java的类就比较相似,如果没有加任何权限修饰符(public,privite)那么Groovy中类和变量都是默认就是public修饰符

然后我们在根目录创建另一个文件Bb.groovy

import com.aa.Aa;

Aa aa = new Aa("小明","小红");
aa.print();

Bb文件先 import com.aa.Aa;然后调用Aa中的print方法

看下执行Bb之后的结果

$ groovy Bb.groovy 
小明小红

脚本到底是什么

在java中,一个类必须要有(class,interface或者其他),不可以不写,但是Groovy可以像写脚本一样,可以直接把想要的事情写入xxx.groovy文件中,而且可以使用 groovy xxx.groovy 来直接执行文件

IO操作

Groovy中的IO操作比java中的简单一些,Groovy的IO操作其实是在Java IO操作上进行了更为简便的封装,并且使用Closure来简化代码,一下是文档地址

java.io.File: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/File.html 
java.io.InputStream: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/InputStream.html 
java.io.OutputStream: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/OutputStream.html 
java.io.Reader: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/Reader.html 
java.io.Writer: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/Writer.html 
java.nio.file.Path: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/nio/file/Path.html

读文件

File

直接查看API文档 java.io.File: http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/File.html

文件内容

你好啊
哈哈哈
class Example {
    
    
   static void main(String[] args) {
    
    
       //创建文件
     def file = new File("text.txt");

    //输出文件的每一行
    file.eachLine{
    
    
        String line ->
        println line;
    }

    //文件内容一次性读出,返回类型为 byte[]
    byte[] aa = file.getBytes()
    String bb = new String(aa);
    println bb;

   }
}

输出

你好啊
哈哈哈
你好啊
哈哈哈

InputStream

首先查看Api文档http://docs.groovy-lang.org/latest/html/groovyjdk/java/io/InputStream.html

 //获取InputStream流
    def ism = file.newInputStream()
    byte[] cc = ism.getBytes()
    String dd = new String(cc);
    println dd;


    //使用闭包操作InputStream,以后在gradle中都是用这种方式
    file.withInputStream{
    
     ism1 ->
    byte[] ee = ism1.getBytes()
    String ff = new String(ee);
    println ff
    //操作 ism. 不用 close。Groovy 会自动替你 close 
   }

输出

你好啊
哈哈哈
你好啊
哈哈哈

写文件

继续看文档 http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/OutputStream.html

 def srcFile = new File("text.txt")

        def targetFile = new File("copy.txt") 

        targetFile.withOutputStream{
    
     os->

        srcFile.withInputStream{
    
     ins->

        //利用 OutputStream 的<<操作符重载,完成从 inputstream 到 OutputStream //的输出
        os << ins 
			} 
		} 

XML操作

Groovy中操作XML也是非常的简洁,首先提供一个xml文件

<response version-api="2.0">
<value>
<books>

<book available="20" id="1">
<title>Don Xijote</title>
<author id="1">Manuel De Cervantes</author>
</book>

<book available="14" id="2">
<title>Catcher in the Rye</title> <author id="2">JD Salinger</author>
</book>

<book available="13" id="3">
<title>Alice in Wonderland</title>
<author id="3">Lewis Carroll</author> 
</book>

<book available="5" id="4">
<title>Don Xijote</title>
<author id="4">Manuel De Cervantes</author>
</book> 

</books>
</value> 
</response>

开始写代码

class Example {
    
    
   static void main(String[] args) {
    
    
        def booksData = new XmlParser().parse("text.xml");
        // 访问第一个book元素的available属性
        def ava = booksData.value.books.book[0].@available
        println ava
        //访问第二个book元素的title
        def data = booksData.value.books.book[2].title.text();
        println data
        //访问第一个book元素的id属性
        def id = booksData.value.books.book[0].@id
        println id

        println "---------------------"
        //遍历boos标签打印title
        booksData.value.books.each{
    
    books->
         books.each{
    
    book ->
            println book.title.text();
         }   
        }
   }
}

输出

20
Alice in Wonderland
1
---------------------
Don Xijote
Catcher in the Rye
Alice in Wonderland
Don Xijote

参考

深入理解Android之Gradle

猜你喜欢

转载自blog.csdn.net/qq_34760508/article/details/114035463