include ‘:myjson’ // 需要参与构建的模块名称
project(‘:myjson’).projectDir = file(‘/Users/WorkSpace/AndroidDemo/MyJson/myjson’)
-
include方法 :指定参与构建的模块的名称,模块名前需要加冒号(:),模块名称可以任取。
-
project方法:加载指定的模块,并为该模块设置一个工程路径,参数必须与include参数一致 。
这样本工程就可以引用到其它位置的模块了,如果引用的是一个 library 模块,那么在本工程的模块中,就可以依赖这个 library 模块了,如:
implementation project(“:myjson”)
1-2、监听初始化过程
在上面的 Settings 类的方法列表中,有一个 getGradle() 方法,返回一个 Gradle 对象,通过这个 Gradle 对象,我们可以监听 Gradle 构建过程中 各个生命周期方法的回调,如在 settings.gradle 文件中,增加如下监听:
gradle.addBuildListener(new BuildListener() {
void buildStarted(Gradle var1) {
println ‘buildStarted()->开始构建’
}
void settingsEvaluated(Settings var1) {
println ‘settingsEvaluated()->settings评估完成(settins.gradle中代码执行完毕)’
// var1.gradle.rootProject 这里访问Project对象时会报错,还未完成Project的初始化
}
void projectsLoaded(Gradle var1) {
println ‘projectsLoaded()->项目结构加载完成(初始化阶段结束)’
println ‘projectsLoaded()->初始化结束,可访问根项目:’ + var1.gradle.rootProject
}
void projectsEvaluated(Gradle var1) {
println ‘projectsEvaluated()->所有项目评估完成(配置阶段结束)’
}
void buildFinished(BuildResult var1) {
println 'buildFinished()->构建结束 ’
}
})
在 build.gradle 文件中,也可以拿到 Gradle 对象,但如果在 build.gradle 文件中添加上面的监听事件的话,buildStarted,settingsEvaluated 和 projectsLoaded 方法是不会回调的,因为这三个方法是在初始化阶段 执行 settings.gradle 文件的时候执行的,但另外两个方法是会回调的。
在根工程的 build.gradle 文件中,增加如下代码,以便更好的观察上面添加的监听事件的回调时机:
allprojects {
afterEvaluate {
println “${name}:配置完成”
}
}
打印信息如下:
settingsEvaluated()->settings评估完成(settins.gradle中代码执行完毕)
projectsLoaded()->项目结构加载完成(初始化阶段结束)
projectsLoaded()->初始化结束,可访问根项目:root project ‘KotlinLearning’
Configure project :
KotlinLearning:配置完成
Configure project :app
app配置完成
Configure project :kotlinlearning
kotlinlearning配置完成
projectsEvaluated()->所有项目评估完成(配置阶段结束)
buildFinished()->构建结束
配置阶段的任务:是执行各项目下的build.gradle
脚本,完成 Project 的配置,并且构造Task
任务依赖关系图以便在执行阶段按照依赖关系执行Task
。
2-1、配置阶段执行的代码
配置阶段也是我们最常接触到的构建阶段,比如应用外部构建插件apply plugin: 'com.android.application'
,配置插件的属性android{ compileSdkVersion 25 ...}
等。
每个build.gralde
脚本文件对应一个Project
对象,在初始化阶段创建,Project
的接口文档。 配置阶段执行的代码包括:
-
build.gralde
中的各种语句 -
闭包
-
Task
中的配置段语句
验证:在根目录的build.gradle
中添加如下代码:
println ‘build.gradle的配置阶段’
// 调用Project的dependencies(Closure c)声明项目依赖
dependencies {
// 闭包中执行的代码
println ‘dependencies中执行的代码’
}
// 创建一个Task
task test() {
println ‘Task中的配置代码’
// 定义一个闭包
def a = {
println ‘Task中的配置代码2’
}
// 执行闭包
a()
doFirst {
println ‘这段代码配置阶段不执行’
}
}
println ‘我是顺序执行的’
打印信息如下:
build.gradle的配置阶段
dependencies中执行的代码
Task中的配置代码 Task中的配置代码2 我是顺序执行的
从上面的打印信息可以看出,在执行了dependencies的闭包后,直接执行的是任务test中的配置段代码(Task
中除了Action外的代码段都在配置阶段执行)
需要注意的是,执行任何 Gradle 命令,在初始化阶段和配置阶段的代码都会被执行。
2-2、Task 依赖关系配置完成监听
配置阶段另外一个重要的任务就是 构建 Task 依赖关系的有向无环图,说简单一点,就是给 所有的 Task 排一个执行顺序,在执行阶段的时候,就按照这个顺序去执行所有的 Task 任务。
我们可以通过 Gradle 对象的 getTaskGraph 方法来得到该有向无环图对象: TaskExecutionGraph,通过TaskExecutionGraph类的相关方法可以监听 Task 依赖关系构建完成的通知,如:
void whenReady(Closure var1)
void addTaskExecutionGraphListener(TaskExecutionGraphListener var1)
在 build.gradle 文件中,增加如下代码:
gradle.getTaskGraph().whenReady {
println “whenReady Task依赖关系构建完成,size=${it.allTasks.size()}”
it.allTasks.forEach { task ->
println “${task.name}”
}
}
gradle.getTaskGraph().addTaskExecutionGraphListener(new TaskExecutionGraphListener() {
@Override
void graphPopulated(TaskExecutionGraph graph) {
println “graphPopulated Task依赖关系构建完成 size=${graph.allTasks.size()}”
graph.allTasks.forEach { task ->
println “${task.name}”
}
}
})
点击运行按钮,运行app的时候,就可以打印出 Task 任务列表
whenReady Task依赖关系构建完成,size=40 preBuild preDebugBuild compileDebugAidl compileDebugRenderscript generateDebugBuildConfig checkDebugAarMetadata generateDebugResValues generateDebugResources mergeDebugResources createDebugCompatibleScreenManifests extractDeepLinksDebug processDebugMainManifest processDebugManifest processDebugManifestForPackage processDebugResources compileDebugKotlin javaPreCompileDebug compileDebugJavaWithJavac compileDebugSources mergeDebugNativeDebugMetadata mergeDebugShaders compileDebugShaders generateDebugAssets mergeDebugAssets compressDebugAssets processDebugJavaRes mergeDebugJavaResource checkDebugDuplicateClasses dexBuilderDebug desugarDebugFileDependencies mergeExtDexDebug mergeDexDebug mergeDebugJniLibFolders mergeDebugNativeLibs stripDebugDebugSymbols validateSigningDebug writeDebugAppMetadata writeDebugSigningConfigVersions packageDebug assembleDebug graphPopulated Task依赖关系构建完成 size=40 preBuild 。。。。。 assembleDebug
执行阶段就是根据配置阶段构建的 Task 依赖关系去执行相关的 Task。
当我们运行项目的时候,Gradle 就会根据 Task的依赖关系依次去执行相关的Task。还可以通过 gradle 命令去执行指定的 Task,如在控制台中输入如下命令,就可以执行 build 任务:
./gradlew build
build 是任务名称。
============================================================================
Gradle 提供了非常多的接口回调以便我们修改构建过程中的行为,整体流程如下图所示:
方法说明:
-
Gradle#settingsEvaluated 方法:与BuildListener的settingsEvaluated的执行时机一样,需要在 settings.gradle 文件中添加,否则无效。
-
Gradle#projectsLoaded 方法:与BuildListener的projectsLoaded的执行时机一样,需要在 settings.gradle 文件中添加,否则无效。
-
Gradle#beforeProject方法,在每个工程 配置之前执行,
-
Project#beforeEvaluate方法,在调用该方法的 Project 配置之前执行,如果在 module 的 build.gradle 文件中调用该方法,是不会执行的,因为执行到build.gradle的时候,已经过了beforeEvaluate执行的时间节点了。
-
Gradle#afterProject方法,在每个工程配置完成之后,执行该方法,哪怕构造过程出错,也会调用,截止到出错的文件。
-
Project#afterEvaluate方法,在调用该方法的Project 配置执行完成之后调用,在这个时机,该工程就配置完成了,如在这个方法回调中就可以获取到所有的Task任务了。
-
Gradle#projectsEvaluate方法,当所有的工程都配置完成之后,执行该方法,与BuildListener的projectsEvaluated方法的执行时机是一样的。
============================================================================
在Gradle中,有三种方式指定task的执行顺序:
-
dependsOn 强依赖方式
-
通过Task输入输出
-
通过API指定执行顺序
dependsOn 强依赖的方式可以细分为 静态依赖 和 动态依赖:
- 静态指定依赖:在创建task的时候,就明确的知道定义的 Task需要依赖的task是什么,直接通过 dependsOn 参数或者 dependsOn 方法指定所依赖的Task。
task提供了dependsOn,finalizedBy方法来管理task之间的依赖关系,依赖关系表达的是执行这个task时所需要依赖的其他task,也就是说这个task不能被单独执行,执行这个 Task 之前或之后需要执行另外的task。
- 动态指定依赖:在创建 Task的时候,不知道需要依赖哪些 Task,通过 dependsOn 方法动态依赖符合条件的 Task
示例代码如下所示:
静态指定依赖
在定义 Task 的时候,直接为 Task 指定 dependsOn 参数,值为 另一个被依赖的 Task 的名字:
task taskX {
doLast{
println ‘taskX’
}
}
task taskY {
doLast{
println ‘taskY’
}
}
task taskZ(dependsOn:taskX) { // 多依赖方式:dependsOn:[taskX,taskY]
doLast{
println ‘taskZ’
}
}
// 当我们执行taskZ的时候,由于依赖了taskX,则taskX会先执行,然后才会执行:taskZ
除了在 Task 定义的时候指定 Task 的依赖之外,还可以通过 Task 的 dependsOn 方法,为 Task 指定依赖:
task taskZ {// 定义Task的时候不指定依赖
doLast{
println ‘taskZ’
}
}
// 通过task的dependsOn方法,也可以指定task的依赖task。
taskZ.dependsOn(taskX,taskY)
当一个task依赖多个task的时候,被依赖的task之间,如果没有依赖关系的话,那么他们的执行顺序是随机的,并无影响。
动态添加依赖
当 Task 在定义的时候,不知道所依赖的 Task 是什么,在配置阶段,通过条件找出符合条件的 Task ,并进行依赖。
task lib1 {
doLask{
println ‘lib1’
}
}
task lib2 {
doLask{
println ‘lib2’
}
}
task lib3 {
doLask{
println ‘lib3’
}
}
// 动态指定taskX依赖所有以lib开头的task
task taskX{
// 动态指定依赖
dependsOn this.tasks.findAll{ task->
return task.name.startsWidth(‘lib’)
}
doLast {
println ‘taskZ’
}
}
当一个参数作为TaskA的输出参数,同时又作为TaskB的输入参数。那么当执行TaskB的时候先要执行TaskA。即输出的Task先于输入的Task执行。 如:
ext {
testFile = file(“${this.buildDir}/test.txt”)
}
// 生产者 Task
task producer {
outputs.file testFile
doLast {
outputs.getFiles().singleFile.withWriter { writer ->
writer.append(“我爱中国”)
}
println “producer Task 执行结束”
}
}
// 消费者 Task
task consumer {
inputs.file testFile
doLast {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
代码真的是重质不重量,质量高的代码,是当前代码界提倡的,当然写出高质量的代码肯定需要一个相当高的专业素养,这需要在日常的代码书写中逐渐去吸收掌握,谁不是每天都在学习呀,目的还不是为了一个,为实现某个功能写出高质量的代码。
所以,长征路还长,大家还是好好地做个务实的程序员吧。
最后,小编这里有一系列Android提升学习资料,有兴趣的小伙伴们可以来看下哦~
mg-Q7kfVM3t-1712056401289)]
[外链图片转存中…(img-lueai4H5-1712056401289)]
[外链图片转存中…(img-JIX5HUBk-1712056401290)]
[外链图片转存中…(img-fcQ3LOgT-1712056401290)]
[外链图片转存中…(img-mNzYUTDF-1712056401290)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-qHofbc7C-1712056401290)]
最后
代码真的是重质不重量,质量高的代码,是当前代码界提倡的,当然写出高质量的代码肯定需要一个相当高的专业素养,这需要在日常的代码书写中逐渐去吸收掌握,谁不是每天都在学习呀,目的还不是为了一个,为实现某个功能写出高质量的代码。
所以,长征路还长,大家还是好好地做个务实的程序员吧。
最后,小编这里有一系列Android提升学习资料,有兴趣的小伙伴们可以来看下哦~