前言
- 欢迎任何形式的转载,转载请保留原文链接:juejin.cn/post/699843…
- 文章性质:非教程,意思是本文目的是便于使用时查阅,以及收集使用记录。所以看不明白的,请自行百度,这里不解释。当然欢迎指出存在的错误,以及新的用法
- 文章主要内容:Gradle 相关笔记,包括配置、教程查找、语法记录,但不包括 Android 本身的 DSL 使用,Android DSL 使用见文章:《Android Gradle 常用配置》
相关资料:
- 下载的 Gradle docs 路径,以 6.6 为例
- 用户手册 PDF:gradle-6.6/docs/userguide/userguide.pdf
- 用户手册:gradle-6.6/docs/userguide/userguide.html
- DSL 手册:gradle-6.6/docs/dsl/index.html
- JavaDoc 手册:gradle-6.6/docs/javadoc/index.html
- 发行说明(即版本迭代说明):gradle-6.6/docs/release-notes.html
- Gradle 官网 API 文档(等同上述 JavaDoc):docs.gradle.org/current/jav…
- Groovy 官网文档:docs.groovy-lang.org/docs/latest…
- Android Gradle 插件
- developer.android.google.cn/reference/t…
- 插件源码:Gradle 下载目录/caches/modules-2/files-2.1/com.android.tools.build/gradle/4.0.2/xxx/gradle-4.0.2-sources.jar
- 其他相关源码:Gradle 下载目录/caches/modules-2/files-2.1/com.android.tools.build
Gradle 配置
本地仓库配置
配置环境变量 GRADLE_USER_HOME,并指向你的一个本地目录,这样 Gradle 下载的所有文件都会保存到这,在也不用担心 C 盘不够用了
Gralde 演示用例
这里为方便后续内容的讲解,这里贴出用例 gradle 代码,匹配的是 Android 项目
/setting.gradle
rootProject.name = 'AndroidCases'
include ':app-cases'
include ':lib-utils'
include ':lib-widget'
/build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
}
}
allprojects {
repositories {
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
/lib-utils/build.gradle
空
Gradle 帮组任务列表
Gradle 本身提供了用于辅助的帮组性质的任务,执行这些任务,可以很方便的查看 gradle 的各种配置,如项目属性之类的
命令行:执行 gralde :lib-utils:tasks 后可以看到以下帮组任务列表
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':lib-utils'.
components - Displays the components produced by project ':lib-utils'. [incubating]
dependencies - Displays all dependencies declared in project ':lib-utils'.
dependencyInsight - Displays the insight into a specific dependency in project ':lib-utils'.
dependentComponents - Displays the dependent components of components in project ':lib-utils'. [incubating]
help - Displays a help message.
model - Displays the configuration model of project ':lib-utils'. [incubating]
outgoingVariants - Displays the outgoing variants of project ':lib-utils'.
projects - Displays the sub-projects of project ':lib-utils'.
properties - Displays the properties of project ':lib-utils'.
tasks - Displays the tasks runnable from project ':lib-utils'.
翻译说明(理解或翻译有误欢迎指出):
buildEnvironment - 显示模块 ':lib-utils' 声明的所有构建脚本依赖项
components - 显示模块 ':lib-utils' 生成的组件。[incubating]
dependencies - 显示模块 ':lib-utils' 声明的所有依赖项
dependencyInsight - 显示模块 ':lib-utils' 特定依赖项的洞察
dependentComponents - 显示模块 ':lib-utils' 组件的依赖组件。[incubating]
help - 显示帮助
model - 显示模块 ':lib-utils' 的配置模型。[incubating]
outgoingVariants - 显示模块 ':lib-utils' 的多样性输出信息(包括自定义,系统,多渠道)
projects - 显示模块 ':lib-utils' 子项目
properties - 显示模块 ':lib-utils' 属性
tasks - 显示模块 ':lib-utils' 所有可运行的任务
或者使用 IDEA 也能查看到
Gradle 生命周期
大方向上的生命周期
为方便说明与讲解,将上述用例加些日志,日志都以 println 开头,这代码可以不用看,直接看日志结果
/setting.gradle
println "settings.gradle begin"
rootProject.name = 'AndroidCases'
include ':app-cases'
include ':lib-utils'
include ':lib-widget'
// 构建监听
gradle.addBuildListener(new BuildListener() {
@Override
void buildStarted(Gradle gradle) {
println "监听:buildStarted"
}
@Override
void settingsEvaluated(Settings settings) {
println "监听:settingsEvaluated"
}
@Override
void projectsLoaded(Gradle gradle) {
println "监听:projectsLoaded"
}
@Override
void projectsEvaluated(Gradle gradle) {
println "监听:projectsEvaluated"
}
@Override
void buildFinished(BuildResult result) {
println "监听:buildFinished"
}
})
// 各个项目监听
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
@Override
void beforeEvaluate(Project project) {
println "监听【${project}】beforeEvaluate"
}
@Override
void afterEvaluate(Project project, ProjectState state) {
println "监听【${project}】afterEvaluate"
}
})
// 依赖配置监听
gradle.addListener(new DependencyResolutionListener() {
@Override
void beforeResolve(ResolvableDependencies dependencies) {
println "监听【${dependencies}】beforeResolve"
}
@Override
void afterResolve(ResolvableDependencies dependencies) {
println "监听【${dependencies}】afterResolve"
}
})
// 任务执行顺序图
gradle.addListener(new TaskExecutionGraphListener() {
@Override
void graphPopulated(TaskExecutionGraph graph) {
println "监听:TaskExecutionGraphListener:${graph.getAllTasks()}"
}
})
// 任务执行监听
gradle.addListener(new TaskExecutionListener() {
@Override
void beforeExecute(Task task) {
println "监听【${task}】beforeExecute"
}
@Override
void afterExecute(Task task, TaskState state) {
println "监听【${task}】afterExecute"
}
})
/**
* 添加监听器,除了上述,还有这些,只是与生命周期无关
* <li>{@link org.gradle.api.execution.TaskActionListener}
* <li>{@link org.gradle.api.tasks.testing.TestListener}
* <li>{@link org.gradle.api.tasks.testing.TestOutputListener}
* <li>{@link org.gradle.api.logging.StandardOutputListener}
*/
println "settings.gradle end"
/build.gradle
println "/build.gradle 【${project}】 begin"
buildscript {
println "/build.gradle buildscript 【${project}】 begin"
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
}
println "/build.gradle buildscript 【${project}】 end"
}
allprojects {
println "/build.gradle allprojects 【${project}】 begin"
repositories {
google()
mavenCentral()
}
println "/build.gradle allprojects 【${project}】 end"
}
println "/build.gradle end"
/lib-utils/build.gradle
println "/lib-utils/build.gradle begin"
apply plugin: 'com.android.library'
// Android 本身的配置,此处省略
project.afterEvaluate {
println "设置【${project}】afterEvaluate,但在这里设置 project.beforeEvaluate 是无效的"
}
println "/lib-utils/build.gradle end"
执行任意任务,以 gradle :lib-utils:bundleDebugAar 为例,日志结果为
Executing tasks: [bundleDebugAar] in project 省略\lib-utils
settings.gradle begin
settings.gradle end
监听:settingsEvaluated
监听:projectsLoaded
> Configure project :
监听【root project 'AndroidCases'】beforeEvaluate
/build.gradle buildscript 【root project 'AndroidCases'】 begin
/build.gradle buildscript 【root project 'AndroidCases'】 end
监听【dependencies ':classpath'】beforeResolve
监听【dependencies ':classpath'】afterResolve
/build.gradle 【root project 'AndroidCases'】 begin
/build.gradle allprojects 【root project 'AndroidCases'】 begin
/build.gradle allprojects 【root project 'AndroidCases'】 end
/build.gradle allprojects 【project ':app-cases'】 begin
/build.gradle allprojects 【project ':app-cases'】 end
/build.gradle allprojects 【project ':lib-utils'】 begin
/build.gradle allprojects 【project ':lib-utils'】 end
/build.gradle allprojects 【project ':lib-widget'】 begin
/build.gradle allprojects 【project ':lib-widget'】 end
/build.gradle end
监听【root project 'AndroidCases'】afterEvaluate
> Configure project :lib-utils
监听【project ':lib-utils'】beforeEvaluate
/lib-utils/build.gradle begin
/lib-utils/build.gradle end
监听【project ':lib-utils'】afterEvaluate
设置【project ':lib-utils'】afterEvaluate,但在这里设置 project.beforeEvaluate 是无效的
> Configure project :省略
监听:projectsEvaluated
监听【dependencies ':app-cases:classpath'】beforeResolve
监听【dependencies ':app-cases:classpath'】afterResolve
监听【dependencies ':lib-utils:classpath'】beforeResolve
监听【dependencies ':lib-utils:classpath'】afterResolve
监听【dependencies ':lib-widget:classpath'】beforeResolve
监听【dependencies ':lib-widget:classpath'】afterResolve
监听【dependencies ':lib-utils:debugCompileClasspath'】beforeResolve
监听【dependencies ':lib-utils:debugRuntimeClasspath'】beforeResolve
监听【dependencies ':lib-utils:debugRuntimeClasspath'】afterResolve
监听【dependencies ':lib-utils:debugCompileClasspath'】afterResolve
监听【dependencies ':lib-utils:lintClassPath'】beforeResolve
监听【dependencies ':lib-utils:lintClassPath'】afterResolve
监听【dependencies ':lib-utils:androidApis'】beforeResolve
监听【dependencies ':lib-utils:androidApis'】afterResolve
监听【dependencies ':lib-utils:debugAnnotationProcessorClasspath'】beforeResolve
监听【dependencies ':lib-utils:debugAnnotationProcessorClasspath'】afterResolve
监听【dependencies ':lib-utils:lintPublish'】beforeResolve
监听【dependencies ':lib-utils:lintPublish'】afterResolve
监听:TaskExecutionGraphListener:[task ':lib-utils:preBuild', task ':lib-utils:preDebugBuild', 省略, task ':lib-utils:bundleDebugAar']
> Task :lib-utils:preBuild UP-TO-DATE
监听【task ':lib-utils:preBuild'】beforeExecute
监听【task ':lib-utils:preBuild'】afterExecute
> Task :省略
> Task :lib-utils:bundleDebugAar UP-TO-DATE
监听【task ':lib-utils:bundleDebugAar'】beforeExecute
监听【task ':lib-utils:bundleDebugAar'】afterExecute
监听:buildFinished
BUILD SUCCESSFUL in 629ms
从上述日志可以看出:
- Gradle 生命周期大体分为:初始化阶段 -> 配置阶段 -> 执行阶段
- 配置阶段又大体分为:项目配置 -> 依赖配置 -> 任务执行顺序图配置
初始化阶段:
- 执行 /setting.gradle,这时候
${project}并不存在,打印的话直接编译错误 - 执行完成后回调:settingsEvaluated
配置阶段:项目配置
1. 这个阶段 ${project} 并已经存在了
2. 各项目执行顺序是:根目录项目配置(/build.gradle) -> 其他 module 项目配置(/module/build.gradle,这个配置顺序规则未知)
3. 整个项目配置前后回调:projectsLoaded、projectsEvaluated
4. 各项目配置前后回调:beforeEvaluate、afterEvaluate
5. 根目录项目配置有点特殊,先走 buildscript 的配置与依赖,然后才正常走 /build.gradle 文件其他内容,其中 allprojects 是每个项目都遍历一遍
6. 除了根目录项目配置,其他的 xxx.gradle 都是从上到下依次执行,即除了监听回调(如 doLast {}),其他的包括闭包,方法,任务等等会依次从上到下执行一次
7. 注意:写在各 module 项目中的 project.beforeEvaluate 是无效的,因为回调时机已经过去了
配置阶段:依赖配置 -> 任务执行顺序图配置
- 各项目依赖配置前后回调:beforeResolve、afterResolve,不过项却大于 module 项目数量,总之自行看日志
- 任务执行顺序图配置仅回调一次:TaskExecutionGraphListener
执行阶段:
- 开始按任务执行顺序图依次执行任务
- 任务执行前后回调:beforeExecute、afterExecute
Android 配置生命周期
没有啥生命周期可言,就是从上到下执行
Gradle 语法与常用 API
相关资料:
- 下载的 Gradle docs 路径,以 6.6 为例
- 用户手册 PDF:gradle-6.6/docs/userguide/userguide.pdf
- 用户手册:gradle-6.6/docs/userguide/userguide.html
- DSL 手册:gradle-6.6/docs/dsl/index.html
- JavaDoc 手册:gradle-6.6/docs/javadoc/index.html
- 发行说明(即版本迭代说明):gradle-6.6/docs/release-notes.html
- Android Gradle 插件
- developer.android.google.cn/reference/t…
- 插件源码:Gradle 下载目录/caches/modules-2/files-2.1/com.android.tools.build/gradle/4.0.2/xxx/gradle-4.0.2-sources.jar
- 其他相关源码:Gradle 下载目录/caches/modules-2/files-2.1/com.android.tools.build
语法糖:
${project}一定能用,而$project不一定能用${this},${super}貌似等同于${project}- API 与属性的引用是可以省略的,至于到底省略的谁得根据上下文,如
- API:在 build.gradle 中行首写
project.afterEvaluate{}可以省略为afterEvaluate{} - 属性:在 Task 的
doLast{ println "属性:${properties}" }的完整写法是doLast { task -> println "属性:${task.properties}" }
- API:在 build.gradle 中行首写
变量作用域
使用 def xxx = ??? 定义的变量
- 在花括号中定义,则只在花括号中有效
- 在 xxx.gradle 中定义,则只在该 gradle 文件中有效
使用 ext.xxx = 定义的变量
- 类似类成员变量,在整个类对象中有效,与定义位置无关
- 至于定义在哪个类对象,则看被省略的引用是哪个实例对象,如
- 在 build.gradle 中定义
ext.custom01 = "custom01"或ext { custom02 = "custom02" },则在任意地方,均可使用project.custom01属性 - 在 Task 中定义
task myTask { ext.custom01 = "custom01" },则在任意地方,均可使用myTask.custom01,注意这里仅myTask任务对象才能用 - Android 项目:
android { applicationVariants.all { variant -> ext.isTest = true } },则在任意地方,均可使用variant.isTest(前提是能拿到 variant 对象)
- 在 build.gradle 中定义
自定义 Class
在 xxx.gradle 中任意地方定义 Class
class TestClass {
String name
String age
}
则关于作用域
- 该 Class 只能在该 xxx.gradle 中文件中
new TestClass() - 关于
def custom01 = new TestClass()、ext.custom02 = new TestClass()见上个标题的《变量作用域》说明- 没错
ext也是能用的,但只能访问与修改custom02的内容,即还是不能自由的new TestClass()
- 没错
那么如何自由的实例化 TestClass 对象呢?
方式一:使用放射的方式绕过去
project.ext.TestClass = TestClass
// 其他文件
def dto = project.TestClass.newInstance()
dto.name = "天才"
方式二:像 Java 那样自由的使用,待确认与补充
Project 相关
查看当前 project 的全部属性:
- 方式一:运行任务【:lib-utils:properties】查看
- 方式二:
println "当前【${project}】项目的全部属性:${project.properties}"
常用综合:
// 属性相关
println "当前【${project}】项目的全部属性:${project.properties}"
// 监听
project.beforeEvaluate {
println "监听【${project}】beforeEvaluate"
}
project.afterEvaluate {
println "监听【${project}】afterEvaluate"
}
Task 相关
获取任务列表清单:运行任务【:lib-utils:tasks】
常用综合:
println "获取当前正在执行的任务列表(不包含依赖任务):${gradle.startParameter.taskRequests}"
// 属性相关
tasks.all { task ->
println "当前【${task}】任务的全部属性:${task.properties}"
}
// 查找任务
Task taskFind = tasks.findByName("assembleDebug")
if (taskFind != null) {
taskFind.doLast {
println "查找到的指定任务【${task}】执行后打印"
}
}
任务依赖、分组等
// 方式一
task01.dependsOn task02
task01.group 'upload'
// 方式二
task task01(group: 'upload', dependsOn: 'task02') {
}
参考文献与版本同步
参考文献:
- 自定义Task类型:www.cnblogs.com/davenkin/p/…
博客同步版本:
- 2021-08-23:首发博客