博客主页

学完了Groovy核心语法后,接下来学习Gradle。

Gradle是一款构建系统工具,它的DSL基于Groovy实现,大部分功能都是通过插件的方法实现的,如果内置插件不能满足需求,可以自定义自己的插件。

Gradle入门及生命周期探索

我们可以参考文档学习Gradle入门。
这里Gradle怎么下载,怎么安装就不说了,可以自行百度学习。
安装完成后,可以通过下面命令校验gradle版本

// Window os
gradlew -v

// Linux os
./gradle -v

现在来编写第一个Gradle脚本

// build.gradle
task hello {
    doLast {
       println "Hello World!"
    }
}

// 执行build.gradle脚本中定义的hello任务
// -q 参数用于控制gradle输出的日志级别,以及哪些日志可以输出被看见
> gradlew -q hello
// 控制台输出信息
Hello World!

build.gradle是Gradle默认的构建脚本文件。定义一个任务(Task),任务的名字为hello,并给任务hello添加一个动作(Action),其实就是Groovy语言实现的闭包。doLast 是Task执行完毕后要回调执行的代码。

Gradle Wrapper

Wrapper,其实就是对Gradle的一层包装,以便开发中统一Gradle的构建版本,避免版本的不统一。
当使用Wrapper启动Gradle时,Wrapper会检查Gradle有没有被下载关联,没有就会从配置的地址下载并运行构建,不需要配置Gradle环境了。

生成Wrapper

我们可以执行Gradle内置的task自动生成Wrapper

> gradlew wrapper

// 将会生成下图的Wrapper配置,gradlew,gradlew.bat文件
// gradlew和gradlew.bat分别是Linux和Windows下的可执行脚本文件,与Gradle原生命令用法一样

在执行gradlew wrapper命令时,也可以指定参数,如:Gradle版本,Gradle下载地址等

// 指定Gradle版本,不指定就默认当前安装的Gradle版本
> gradlew wrapper --gradle-version 4.1

该参数影响的是gradle-wrapper.properties配置中的distributionUrl的值,该值的规则:distributionUrl=https\://services.gradle.org/distributions/gradle-${gradle-version}-all.zip

自定义Wrapper Task

build.gradle构建文件中自定义Wrapper Task

task wrapper(type: Wrapper) {
    gradleVersion = '5.1'
}

> gradlew wrapper

执行完task后,就会生成5.1版本的Wrapper,就不需要手动指定Gradle版本。

Gradle日志

日志级别

Gradle日志级别增加了QUIETLIFECYCLE两个级别。Gradle日志级别如下:
ERROR 错误消息
QUIET重要消息
WARNING警告消息
LIFECYCLE进度消息
INFO信息消息
DEBUG调试消息

// -q 或者 --quite 输出QUIET级别及其之上的日志信息
> gradlew -q tasks

// -i 或者 --info 输出INFO级别及其之上的日志信息
> gradlew -i tasks

// 不加选项,输出LIFECYCLE级别及其更高级别
// -d 或者 --debug 输出DEBUG级别及其更高级别,这个会输出所有日志

输出Gradle错误堆栈信息

默认情况下,堆栈信息的输出是关闭的,可以通过命令行增加参数的形式打开它,在构建失败时,Gradle就会输出错误堆栈信息

// 推荐使用-s,因为-S输出的堆栈信息太多
> gradlew -s tasks

// -s 或者 --stacktrace  输出关键的堆栈信息
// -S 或者 --full-stacktrace 输出全部堆栈信息

脚本中添加日志输出

一般情况下,我们都是使用print系列的方法输出日志,它的级别为QUIET

println '输出的日志信息'

还可以使用内置的logger输出不同级别的日志信息:

logger.quiet('quiet日志')
logger.lifecycle("lifecycle日志")

其实内部实现就是调用ProjectgetLogger()方法获取Logger对象的实例。

Gradle命令行

查看帮助文档命令

一般查看帮助文档,只需在命令后加上-h 或者 --help,有的是-?

> gradlew -?
> gradlew -h
> gradlew --help

查看所有可执行的Tasks

执行下面命令后,会列出所有可执行的task

> gradlew tasks

强制刷新依赖

主要为了解决缓存引发的问题,通过下面命令重新下载依赖,不会走缓存

> gradlew --refresh-dependencies assemble

多任务调用方式

通过命令执行多个任务,只需要按顺序以空格隔开即可,比如下面命令,先是执行clean进行文件清理,再执行打包命令

> gradlew clean assembleArmDebug

Gradle生命周期探索

https://docs.gradle.org/3.3/u...

Gradle构建过程通常分为三步

初始化阶段 Initialization

Gradle支持单个和多个工程的编译。在初始化阶段,Gradle判断需要参与编译的工程,为每个工程创建一个Project对象。

在这个阶段,Gradle会创建Settings对象,并在其上执行settings.gradle脚本,建立工程之间的层次关系。

配置阶段 Configuration

在这个阶段,Gradle会分别在每个Project对象上执行对应的build.gradle脚本,对Project进行配置。

执行阶段 Execution

在执行阶段,Gradle会判断配置阶段创建的哪些Task需要被执行,然后执行选中的每个Task。

在Gradle中可以监听各阶段:
在settings.gradle文件中

println "初始化阶段开始..."

在build.gradle文件中添加监听回调

this.afterEvaluate {
    println "配置阶段完成之后的监听回调"
}

this.gradle.buildFinished {
    println "gradle执行完毕后的监听回调"
}

Gradle构建脚本基础探索

settings文件

在Gradle中,settings文件主要用于初始化以及工程树的配置,默认名为settings.gradle,存放在项目根目录下。

根工程相当于Android Studio中的Project,一个根工程可以有多个子工程,也就是多个Module。
一个子工程只有在settings.gradle文件中配置了,Gradle才能识别,也就是在构建时在包含进入。

include ':app', ':basiclib'

build文件

每个Project都会有一个Build文件,该文件是该Project构建入口。可以配置版本,插件,依赖库等。

Root Project也有一个Build文件,在该文件中可以获取所有的Child Project,所以我们可以对Child Project统一配置,如插件,依赖Maven仓库等,这样就不用对每个Project去配置。如果配置所有的Child Project仓库为jcenter,可以如下配置:

subprojects {
    repositories {
       println "subprojects>> name: ${project.getName()}"
       jcenter()
    }
}

除了subprojects外,还提供了allprojects,这个是对所有的Project配置。

Projects 、Tasks

一个Project可以由多个Task组成。其实Task就是一个原子性操作,比如:打个jar包,复制一份文件,上次jar到Maven中心仓库等。

创建一个task

task customTask {
    doFirst {
        println "custom task>>> doFirst"
    }

    doLast {
        println "custom task>>> doLast"
    }
}

// 执行任务, -s 输出错误堆栈信息
> gradlew -s customTask

task 其实是Project对象的一个函数,customTask 为任务的名字。原型:Task task(String name, Closure configureClosure),Groovy语法中,最后一个参数是闭包时,可以放在括号的外面,而方法的括号可以省略。

还可以通过TaskContainer创建任务,Project对象已经定义好了一个TaskContainer

tasks.create("customTask") {
    doFirst {
        println "TaskContainer custom task>>> doFirst"
    }

    doLast {
        println "TaskContainer custom task>>> doLast"
    }
}

// 执行任务, -s 输出错误堆栈信息
> gradlew -s customTask

任务依赖

任务之间可以有依赖关系,也就是说一个任务执行完后,才能执行其他任务。可以通过dependsOn指定其依赖的任务。

task customTask1 {
    doLast {
        println "customTask1 running."
    }
}

// customTask2的执行会依赖于customTask1
task customTask2(dependsOn: customTask1) {
    doLast {
        println "customTask2 running."
    }
}

> gradlew  customTask2

// 输出打印信息,customTask1 会优先 customTask2 执行
customTask1 running.
customTask2 running.

一个任务也可以同时依赖多个任务,dependsOn是Task类的一个方法,可以接受多个依赖的任务作为参数

task customTask1 {
    doLast {
        println "customTask1 running."
    }
}

task customTask2 {
    doLast {
        println "customTask2 running."
    }
}

task customTask3 {
    // customTask3 的执行,依赖于customTask1 , customTask12
    // 多个任务,用逗号隔开,在前面的任务会先执行,如:customTask1任务
    dependsOn customTask1, customTask2
    doLast {
        println "customTask3 running."
    }
}

// 执行customTask3任务
> gradlew customTask3

// 输出打印信息,
:customTask1
customTask1 running.

:customTask2
customTask2 running.

:customTask3
customTask3 running.

通过任务名操作任务

可以通过任务名(任务类型是Task),使用Task的API访问它的方法、属性、或者对任务重新配置。

task customTask1 {
    println "customTask1 running."
}

customTask1.doFirst {
    println "customTask1 doFirst running."
}

customTask1.doLast {
    println "has customTask1 property ${project.hasProperty('customTask1')}"
    println "customTask1 doLast running."
}

// 执行任务
> gradlew customTask1

// 输出打印信息
customTask1 running.
customTask1 doFirst running.
has customTask1 property true
customTask1 doLast running.

从上面脚本中可知,可以调用 doFirstdoLast 方法,在任务执行前后做一些操作。使用任务名操作任务的原理是:Project在创建该任务的时候,同时把该任务对用的任务名注册为Project的一个属性,类型为Task。通过project.hasProperty(String propertyName)可以检查是否有这个属性。

自定义属性

Project和Task都可以添加额外的自定义属性,通过应用所属对应的ext属性实现。如果自定义多个属性,使用代码块。可以跨Project,跨Task访问自定义属性。

// 自定义有个Project属性
ext.myName = 'kerwin'

// 自定义多个属性通过代码块
ext {
    myAge = 12
    myPhone = 13564954189
}

task customTask {
    doLast {
        println "myName: ${myName}"
        println "myAge: ${myAge}"
        println "myPhone: ${myPhone}"
    }
}
// 执行任务
> gradlew customTask 
// 输出结果
myName: kerwin
myAge: 12
myPhone: 13564954189

如果我的文章对您有帮助,不妨点个赞鼓励一下(^_^)


小兵兵同学
56 声望23 粉丝

Android技术分享平台,每个工作日都有优质技术文章分享。从技术角度,分享生活工作的点滴。