前言

在前几篇中,讲解了Groovy的基础语法,学习新语法过程总是枯燥的,但为了更好的掌握Gradle,那就必须经过该过程。当然从这一篇将会从零基础开始,开展对Gradle的讲解。

1. 掌握Gradle基础

1.1 环境配置

  • 去官网下载gradle或者从本地用户文件夹下的.gradle/wrapper/dists找到本地缓存的gradle开发工具包 (注意带bin文件夹的这个grade-x.x)
  • 系统属性配置:
  1. 添加GRADLE_HOME:C:\Users\sheji.gradle\wrapper\dists\gradle-6.5-all\gradle-6.5
  2. 添加Path:%GRADLE_HOME%\bin
  • 检查配置

CMD 命令窗口输入 gradle -v,看看是否显示当前Gradle版本

1.2 Hello Gradle!

我们学习任何开发语言,第一个程序都离不开Hello 程序。所以仪式感还是要有的。

  1. 在工程文件夹下,创建一个build.gradle文件:
  2. 在文件里写入代码
    task hello{println 'Hello, Gradle!'
    }
    
  3. 打开cmd终端,移动到工程目录下,执行命令:> gradle -q hello
  4. 最终效果

如图所示

当运行成功时,将会自动创建.gradle文件夹。

此时我们继续在这个命令窗口执行命令:gradle wrapper
将会看到

如图所示

在本目录里面,系统自动帮我们创建了一系列文件以及文件夹,这些文件都似曾相识,打开AS和idea对比一下,发现目录里面有的对应编译器都会有。

这就是一个很标准的gradle工程目录结构:

gradlew和gradlew.bat分别是Linux和Windows下的可执行脚本,具体业务逻辑是在/gradle/wrapper/gradle-wrapper.jar中实现,gradlew最终还是使用Java执行这个jar包来执行相关的Gradle操作的。

1.2.1 gradle-wrapper.properties解读

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

这段代码就是这个文件里面的内容,现在将逐一进行解读

  • distributionBase:下载的Gradle压缩包解压后存储的主目录
  • distributionPath:相对于distributionBase的解压后的Gradle压缩包的路径
  • distributionUrl:Gradle发行版压缩包的下载地址
    • -bin:二进制发布版
    • -all:bin基础上还包含了源码和文档
  • zipStoreBase:同distributionBase,只不过存放的是zip压缩包的
  • zipStorePath:同distributionPath,只不过存放的是zip压缩包的

而 distributionBase对应的值为:GRADLE_USER_HOME

1.2.2 GradleUserHome 属性解读

  • 默认路径在~/.gradle/ ,不建议使用本地maven的m2替代,因为原本的.gradle目录下的模块分的很清晰,功能明确
  • 如果启动时,指定参数,使用别的目录代替GradleUserHome ,后果是每次构建需要重新下载插件与依赖到新的目录
  • 默认情况下,gradle运行时,除了和项目打交道,还有当前项目构建的全新的GradleUserHome目录,所有jar包都得重新下载

1.3 Gradle部分命令行

  • gradlew -?/-h/-help 使用帮助
  • gradlew tasks 查看所有可执行Tasks
  • gradlew --refresh-dependencies assemble 强制刷新依赖
  • gradlew cBC 等价与执行Task cleanBuildCache,这种通过缩写名快速执行任务
  • gradlew :app:dependencies 查找app工程依赖树

2. 熟悉Gradle构建机制

2.1 熟悉setting.gradle的作用

我们继续看 Java、Android工程目录

如图所示

这里我们看到:这个俩个工程目录比刚刚多了个setting.gradle文件,现在来单独说明下这个文件具体有啥作用:

  • Gradle支持多工程构建,使用settings.gradle来配置添加子工程(模块)
  • settings文件在初始化阶段执行,创建Settings对象,在执行脚本时调用该对象的方法
  • Settings.include(String… projectPaths)
    • 将给定的目录添加到项目构建中,’:app’表示文件相对路径,相当于’./app’文件夹
    • 多项目架构进行分层,把同层次的子工程放在同一文件夹下便于管理,使用’:xxx:yyy’表示

刚刚也说明了,settings文件在初始化阶段执行,那么其他阶段有哪些呢?这就要从Gradle生命周期开始说起了。

2.2 熟悉Gradle生命周期

Gradle生命周期无非就是这三个:Initialization、Configuration、Execution

  • Initialization

    • Gradle支持单项目和多项目构建。在初始化阶段,Gradle确定哪些项目将参与构建,并为每个项目创建Project实例,一般我们不会接触到它。(比如解析settings.gradle)
  • Configuration
    • 配置阶段,解析每个工程的build.gradle文件,创建要执行的任务子集和确定各种任务之间的关系,并对任务的做一些初始化配置。
  • Execution
    • 运行阶段,Gradle根据配置阶段创建和配置的要执行的任务子集,执行任务。

而这三个生命周期又与执行流程息息相关。

2.3 熟悉Gradle执行流程


如图所示

从这张图可知,不同的阶段都有对应方法的调用顺序,在这里我们暂可熟悉这些即可:

  1. 初始化阶段里面的Setting.gradle
  2. 配置阶段的所有
  3. 执行阶段的所有

刚刚已经讲解了setting.gradle的作用,现在接着讲解配置阶段相关的内容。

2.4 熟悉Gradle配置阶段

  1. 解析每个Project中的build.gradle,解析过程中并不会执行各个build.gradle中的task。
  2. 经过Configration阶段,Project之间及内部Task之间的关系就确定了。一个Project包含很多Task,每个Task之间有依赖关系。Configuration会建立一个有向图来描述Task之间的依赖关系,所有Project配置完成后,会有一个回调project.afterEvaluate(),表示所有的模块都已经配置完了。

因为这里配置阶段和Gradle对应的Task(任务列表)相互绑定,所以这里不好拿代码单独解释配置相关的方法,需要结合Gradle任务一起讲,所以这里先忍耐一下,等讲完Task(任务列表)后,再一起解析。

2.5 熟悉Gradle任务

Gradle Task:

  • task是gardle中最小的任务单元,任务之间可以进行复杂的操作(如动态创建任务,多任务间依赖调用等等)。gradle的执行其实就是由各种任务组合执行,来对项目进行构建的
  • 使用gradlew help命令,任何gradle项目都有一个该task,可以执行此命令观察taks执行的流程是否如预期
  • 可以使用工具查看,还可以通过 gradlew tasks 命令查看可运行任务。
    • 使用gradlew tasks --all 命令查看所有任务
    • 使用gradlew A B 命令表示执行任务A和B,支持驼峰简写

注:task是gardle中最小的任务单元,犹如我们现在所常用的金钱单位0.01元一样(别钻牛角尖)。

概念都说了一大堆,接下来就到了愉快的撸码验证环节了。

创建java环境下的Gradle工程项目,进入build.gradle


this.beforeEvaluate {println "this.beforeEvaluate"
}
//等同beforeEvaluate
this.gradle.beforeProject {println "this.beforeProject"
}this.afterEvaluate {println "this.afterEvaluate"
}
//等同配置阶段完成后
this.gradle.afterProject {println "this.afterProject"
}this.gradle.taskGraph.whenReady{println "whenReady"
}// Gradle3.0 << ,在4.x以上就废弃了
task A {println "configuration A.."doFirst {println "doFirst A.."}doLast {println actionsprintln "doLast A1.."}}task B{println "configuration B.."doFirst {println "doFirst B.."}doLast {println actionsprintln "doLast B1.."}
}this.gradle.buildFinished {println "buildFinish"
}

代码解析

这里面开头那几个this指向对应的方法,就是刚刚我们执行流程图对应的方法,过后又定义了两个task任务单元,里面分别对不同的action有不同的打印输出,接下来我们看看运行效果:

运行效果一:运行taskA


如图所示

点击右边任务列表中的task或者点击左侧对应task的运行按钮

> Configure project :
configuration A..
configuration B..
this.afterProject
this.afterEvaluate
whenReady> Task :A
doFirst A..
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@261ae6e0, org.gradle.api.internal.AbstractTask$ClosureTaskAction@76e733fb]
doLast A1..
buildFinish

我们发现在配置阶段,两个Task里面的 configuration 都被打印了出来,随后就打印了配置结束的方法,以及准备进入到执行阶段的whenReady方法。因为运行的A任务,所以随后就进入了taskA的执行阶段,在执行阶段里,优先运行的doFirst 其次是doLast 对应的action,最后如愿的调用了buildFinish方法来结束整个Gradle编译。

不过这里有个小瑕疵:运行发现,配置前的beforeEvaluate、beforeProject对应方法并没有打印出来,如有知情的大佬知道其原因欢迎相互交流。不过这并不影响我们的发挥,因为每个任务的配置代码在构建的时候都会执行。

我们发现,单独运行A或者B的时候,配置阶段都执行了对应任务里面的配置,唯独运行没有一起运行,而我们在使用Android Gradle的时候,都是扒拉扒拉全运行完,就像配置阶段一样。那我们要怎样做呢?

task A {println "configuration A.."doLast {println actionsprintln "doLast A1.."}}task B{println "configuration B.."doLast {println actionsprintln "doLast B1.."}
}A.dependsOn B

在这里我这只加了 A.dependsOn B 这段代码,看着意思就有点像,A继承B,运行一下A试试:

> Configure project :
configuration A..
configuration B..> Task :B
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@213f5745]
doLast B1..> Task :A
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@70cabab9]
doLast A1..

我们发现,运行A的时候,两者都一起运行了,但是问题来了,当我运行B的时候,又变成了单独运行,而且如果出现多个task怎么办呢?总不能相互 dependsOn 吧?

接下来又对代码进行一系列改造:

task A {println "configuration A.."doLast {println actionsprintln "doLast A1.."}}task B{println "configuration B.."doLast {println actionsprintln "doLast B1.."}
}task C {println "configuration C.."doLast {println "doLast C.."}
}task hello2(dependsOn: [A, C, B]) {doLast {println "doLast hello2"}
}

这里我们看出,这里定义了新的任务hello,随后将已存在的task通过数组的形式相互绑定,换句话说,就是定义了一个管理类,将所有零散的任务单元全部管理了其他,想运行所有任务单元,只需要运行这个管理类即可。所以运行一下hello2任务单元试试:

> Configure project :
configuration A..
configuration B..
configuration C..> Task :A
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@40880123]
doLast A1..> Task :B
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@111c4be4]
doLast B1..> Task :C
doLast C..> Task :hello2
doLast hello2BUILD SUCCESSFUL in 0s
4 actionable tasks: 4 executed
18:33:17: Task execution finished 'hello2'.

在代码里,我特意将 B和C相互兑换位置,结果发现,运行单位元,就是按照字母排序的方式依次运行。

现在又有新的问题,我们在使用任何对象的时候,使用完了都会被回收掉,那么任务执行完了,是不是也会有对应的回收任务?那该使用什么关键字呢?

接下来继续改造代码:

task A {println "configuration A.."doLast {println actionsprintln "doLast A1.."}}task B{println "configuration B.."doLast {println actionsprintln "doLast B1.."}
}task C {println "configuration C.."doLast {println "doLast C.."}
}task hello2(dependsOn: [A, C, B]) {doLast {println "doLast hello2"}
}task finalized {doLast {println "clear all tasks"}
}hello2.finalizedBy finalized

这里我们看到,又新增了一个task,里面表示执行清理逻辑,随后使用了 finalizedBy 关键字将,任务总管理和清理任务相互关联,运行效果看看

> Configure project :
configuration A..
configuration B..
configuration C..> Task :A
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@25b5129e]
doLast A1..> Task :B
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@74447d23]
doLast B1..> Task :C
doLast C..> Task :hello2
doLast hello2> Task :finalized
clear all tasks

到这里,我们应该大概对Gradle任务有所了解了,每一个任务task都是最小单位,而每个task里都有对应的actions。而Gradle构建就是每一个任务单位相互执行后的结果。

结束语

本篇讲解到这里就结束了,相信你对Gradle基础以及构建机制有所认知,在下一篇里,将会继续对Gradle进行深一步的讲解。

Android—Gradle教程(一)相关推荐

  1. android Gradle 教程

    发现一个官方翻译后的gradle教程:http://avatarqing.github.io/Gradle-Plugin-User-Guide-Chinese-Verision/index.html

  2. gradle教程 [原创](eclipse/ADT下 非插件 非Android Studio/AS)纯手打 第一篇:安装配置gradle...

    一个bug 一个脚印的叫你们用gradle. 1介于网络上的很多资料都是老的 不适用与现在的新版本gradle 尤其是有些gradle方法改名了老的用不了 2介于网上都是粘贴复制并且零碎我很蛋疼啊,走 ...

  3. Android 测试教程

    Android 测试教程:http://wiki.jikexueyuan.com/project/android-test-course/ 每个开发者都应该懂一点单元测试 一.什么是单元测试? 为了测 ...

  4. Android入门教程免费获取

    场景 AndroidStudio下载安装教程(图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103672471 几百 ...

  5. 读书笔记--Android Gradle权威指南(上)

    本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 最近看了一本书<Android Gradle 权威指南>,对于 Gradle 理解又更深了,但不想过段时间就又忘光了,所 ...

  6. Android Studio 教程(1)----配置

    Android Studio 教程 配置 [Android Studio的优势] 基于Gradle的构建支持 Android特定重构和快速修复 更加丰富的模板代码,让创建程序更简单 提示工具更好地对程 ...

  7. Android入门教程:ConstraintLayout约束布局

    原文首发自掘金芦苇APP团队,转载到自己小号上再发一遍~ 翻译By Leelion6.关于 ConstraintLayout 的文章其实已经不少了,不过看到这篇文章写的很有趣,以及在翻译的过程中,感受 ...

  8. Android Volley教程

    In this android volley tutorial, we'll be implementing the Volley library in our application. If you ...

  9. Android Studio教程– Hello World App

    Welcome to the Android Studio Tutorial. This is the first article in the android tutorial series and ...

  10. android实例教程_Android ConstraintLayout示例教程

    android实例教程 In this tutorial, we'll discuss the intricacies of android ConstraintLayout. Google had ...

最新文章

  1. WCF获取客户端IP和端口
  2. Win32SDK中(串行)通信资源概要(不断更新)
  3. [Java开发之路]Java字符串
  4. 成功解决SyntaxError: import * only allowed at module level
  5. android 麦克风耳机,Android force AudioRecord使用耳机麦克风
  6. Android安全与逆向之Dex动态加载
  7. eureka server配置_springcloud+eureka整合分布式事务中间件seata
  8. 64位百度云 catia v6_福利缩水:百度网盘决定收回部分储存空间
  9. php七牛云rtmp直播推流,GitHub - jangocheng/FlutterQiniucloudLivePlugin: Flutter 七牛云直播云 推流/播放 SDK集成...
  10. 数据库 查询XML XQuery
  11. 浅析Vue.js 中的条件渲染指令
  12. OSPFv3中LSA详解(四)——Link LSA详解
  13. Duplicate class com.blankj.utilcode.BuildConfig found in modules classes.jar
  14. BT种子文件(.torrent)的具体文件结构
  15. NLP的两种工具的java版使用:复旦FudanNLP,中科院计算所ICTCLAS2013
  16. 经典.net混淆器 Confuser EX 2.0 使用介绍及配置 2022
  17. 项目经理要“谋定而后动,知止而有得,万事皆有法,不可乱也”
  18. 以下不是python3保留字的是_python 保留字
  19. python股票买卖问题_714. 买卖股票的最佳时机含手续费(Python)
  20. Django——创建数据库和表

热门文章

  1. LayoutInflater解析
  2. 【rmzt:进击的巨人炫彩主题】
  3. SAP在阿里云白皮书-第二章 阿里云概念解析
  4. 07-PKI证书体系
  5. DNF11.22服务器维护到几点,11.22体验服更新详情,文字版。预计正式服更新是11.26...
  6. CEikEdwin 助手
  7. python画围棋棋盘_python3 turtle 画围棋棋盘
  8. python提取格式化日志
  9. C# WPF做的漂亮的登陆界面[附源码]
  10. pytorch使用万能模板