Gradle学习

Gradle学习

第一章:Gradle 入门

1. 环境搭建

基础环境为Ubuntu16.04

java 安装

sudo apt install openjdk-8-jdk

gradle安装

在官网下载安装包解压到安装目录,在用户目录下.bashrc 文件中或者/etc/profile中添加环境变量配置。

GRADLE_HOME=/root/UbuntuHome/gradle-2.14
PATH=${PATH}:${GRADLE_HOME}/bin
export GRADLE_HOME PATH

在shell中输入source ~/.bashrc 使配置生效。gradle -v 查看是否安装成功。

2. Groovy基础

Groovy是基于Jvm虚拟机的一种动态语言,支持闭包、DSL等特性。Gradle脚本使用Groovy编写。本文将在此处简单介绍Groovy的语法。、

单独安装groovy环境只需要在https://github.com/apache/groovy/releases下载安装包,解压缩后创建环境变量 GROOVY_HOME=/opt/groovy/groovy-2.6.0 再将$GROOVY_HOME/bin加入到PATH环境变量中。

或者使用如下命令:

apt install curl zip unzip
curl -s get.sdkman.io | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install groovy

使用gvm来管理groovy版本。

$ gvm install groovy
$ gvm install groovy 2.1.9
$ gvm use groovy 2.2.0
$ gvm uninstall groovy 2.1.9
$ gvm list groovy

Groovy 和Java语法很相似,此处挑选一些基础特征作对比。

变量
class First {
    static void main(String[] args) {
        String a = 'Hello Single'
        String b = "Hello Double"
        def str1 = '单引号'
        def str2 = "双引号"
        println(a)
        println "双引号有运算能力${a}"
        println '单引号没有运算能力${b}'
    }
}

(1) Groovy中结尾分号不是必须的,单引号和双引号都是字符串,区别在于双引号可以进行表达式计算。${a+b} 或者 ${a} 只有一个变量时可以省略括号。

(2)Groovy中可以指明类型声明变量,也可以使用def 声明变量,具体类型由对象决定。

(3)脚本中声明的变量默认都是public修饰的。

数组

Groovy 中使用[ ] 创建数组,数组需要指明类型

String[] strings = ["aaa", "bbb", "ccc","ddd","eee"]
def ints = [1, 2, 3, 4] as int[];

println(strings)
println(ints)
println(strings[-1])
println(strings[0,-1])
println(strings[1..2])

[1] 取出指定位置的一个元素,返回单个元素。

[0,2,6,8,-1] 取出指定位置的多个元素,返回数组列表。

[1..6] 取出索引1 到索引6 的所有元素,返回数组列表。

数组遍历可以使用each方法,使用闭包作为参数,it是默认的遍历数据项。

strings.each {
    println(it)
}
List

Groovy的List和数组很像,区别在于List不用指定元素类型,一个列表可以包含多种类型的元素。还可以使用<<向列表内添加元素。

ArrayList arrayList =["name",23,true,22.33333]
LinkedList linkedList = ["name",23,true,22.33333]
List list = ["aaa",linkedList,22]
def list2 = ['list2','bbb',arrayList,list,linkedList]

list2 << 3
list2 << arrayList

其他元素访问方式和遍历方式和数组一样。

Map

map存储key-value 形式数据,使用:连接key-value,使用,作为分隔符。

map.[‘key’] 或者 map.key 访问元素

基本使用如下:

def map1 = ["key": 34, "key2": "value", 34: 333]
map1["key3"] = 44
def key4 = "key4"
map1[key4]=55
println(map1)
println(map1["key2"])
println(map1.key2)
map1.each {
    println(it.key + "   " + it.value)
}
方法

Groovy中的方法很灵活

def mothe1(String a, b) {
    println(a)
    println(b)
    "${a}  -----    ${b}"
}

void method2() {
    println("method2")
}

使用def定义方法,无需指定返回类型,如果没有指定return语句则默认使用最后一个表达式的值作为返回值。当没有返回类型时使用void

方法入参可以指定类型,也可以不指定类型。

def first = new First();
def result
result = first.mothe1("aaa", 34)
result = first.mothe1 "aaa",34
println(result)
first.method2()

有参时方法调用可以省略掉( ) 无参时不能省略。

在一个Groovy脚本中可以定义多个public 类,且方法和类默认就是public的。

class Car {
    public def name
    String company
    float price
}

编译后得到Car.class文件,当成员变量没有访问修饰符时,会自动生成set 和get 方法。

public class Car implements GroovyObject {
    public Object name;
    private String company;
    private float price;

    @Generated
    public Car() {
        CallSite[] var1 = $getCallSiteArray();
        super();
        MetaClass var2 = this.$getStaticMetaClass();
        this.metaClass = var2;
    }

    @Generated
    public String getCompany() {
        return this.company;
    }

    @Generated
    public void setCompany(String var1) {
        this.company = var1;
    }

    @Generated
    public float getPrice() {
        return this.price;
    }

    @Generated
    public void setPrice(float var1) {
        this.price = var1;
    }
}

Groovy 中可以在没定义成员变量时,使用访问成员变量的方式调用get方法。

class People {
    String name
    int getAge() {
        return 18;
    }
}

People p = new People()
print(p.age)

所以p.age 是调用方法,而不是访问成员变量。

闭包

闭包是DSL的基础,是groovy的一个很重要的特性,可以将一段代码作为参数传入到方法中,java8中使用lambda实现闭包的功能。

定义:闭包其实就是一段花括号包围的代码块;

{ [(参数1,参数2)->] 运行代码 }

参数列表使用()包围,当只有一个参数时可以省略括号,当没有参数时可以省略->

groovy规定闭包只有一个参数时,可以不自己定义,使用it 作为参数。

groovy规定如果方法最后一个参数为闭包,则可以将闭包放到参数列表外部。

闭包内可以访问脚本中定义的变量。

// 定义需要闭包参数的方法
def runClosure(len,Closure closure) {
    for (int i in 1..len) {
        closure(i)
    }
}
// 定义闭包作为变量
def a = { b -> println("我是单独实现的闭包:${b}") }
// 调用方法传入闭包参数
runClosure(10,a)
runClosure.call(10,a)
// 将末尾的闭包参数放置参数列表外部
runClosure(10) { b -> println("调用时实现的闭包:${b}") }

好玩的来了,上面的方法需要len 和 closure两个参数,如果这个方法只需要一个closure 类型的参数呢?

def startClosure(code) {
    for (int i in 1..5) {
        code(i)
    }
}
// 使用自定义的参数作为入参
startClosure { i -> println "结果为:${i * i + 1}" }
// 使用默认的it参数作为入参
startClosure {
    println "结果为:${it * it +1}"
}

是不是很熟悉,以上就是在gradle脚本中大量见到的闭包使用方式。

闭包委托

Closure对象中有三个属性,thisObject、owner、delegate

thisObject:指向定义闭包时所在的类或者实例对象。如果闭包是在脚本中创建,则this指向脚本类实例对象;如果闭包是在实例对象方法中创建,那this指向实例对象;如果是闭包嵌套创建的闭包,那也指向实例对象。

owner:和this类似,区别在于当在闭包A中创建闭包B,指向的是闭包A。

delegate:默认情况下和owner相同,我们也可以创建闭包后将其指向第三方实例对象。

class ClassC {
    def test(){
        println("******************************")
        println("ClassC "+this)
        def closureA = {
            println("closure A  this  " + thisObject)
            println("closure A  owner  " + owner)
            println("closure A  delegate  " + delegate)

            def closureB = {
                println("closure B  this  " + thisObject)
                println("closure B  owner  " + owner)
                println("closure B  delegate  " + delegate)

                def closureC = {
                    println("closure C  this  " + thisObject)
                    println("closure C  owner  " + owner)
                    println("closure C  delegate  " + delegate)
                }
                closureC()
            }
            closureB()
        }
        closureA()
    }
}

ClassC c = new ClassC();
c.test()

当在闭包内调用一个属性或者一个方法时,会依次在this->owner->delegate 中查找是否有对应的属性或方法。当然这个顺序是可变的需要按如下方式配置

closure.setResolveStrategy(Closure.DELEGATE_FIRST)
  • Closure.OWNER_FIRST,默认策略,首先从owner上寻找属性或方法,找不到则在delegate上寻找。
  • Closure.DELEGATE_FIRST,和上面相反。首先从delegate上寻找属性或者方法
  • Closure.OWNER_ONLY,只在owner上寻找,delegate被忽略。
  • Closure.DELEGATE_ONLY,和上面相反。只在delegate上寻找,owner被忽略。
  • Closure.TO_SELF,高级选项,让开发者自定义策略。

3.Gradle项目结构

通常项目结构都是由总到分的树状结构,Gradle项目也是如此。

settings.gradle

位于工程目录下,进行工程数的初始化和配置工作。一个工程可以包含多个project,settings.gradle 文件中声明了根工程名称、包含的子projet 及其目录。

// 根工程名称
rootProject.name = 'android-gradle-book-code'
// 子projet2
include ':example02'
project(':example02').projectDir = new File(rootDir, 'chapter01/example02')
// 子project3
include ':example03'
project(':example03').projectDir = new File(rootDir, 'chapter01/example03')

当不指定子工程目录时,默认使用当前setting.gradle同级目录下子工程同名的目录作为子工程目录。

build.gradle

每个project目录下都有一个build.gradle 文件,是该project构建的入口,可配置版本、需要的插件、依赖库。

当然根工程目录下也有一个build.gradle文件,可以在此设置全局的仓库入口,全局可用的插件等。如下就是

buildscript {
    repositories {
        maven { url "https://jitpack.io" }
        jcenter()
    }
    dependencies {
        classpath 'org.jacoco:org.jacoco.core:0.7.4.201502262128'
    }
}
allprojects {
    repositories {
        maven { url "https://jitpack.io" }
        jcenter()
    }
}
subprojects {
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值