gradle 安卓构建流程
一.gradle 构建流程主要分为三个阶段:
(1).初始化阶段
(2).配置阶段
(3).执行阶段
1.初始化阶段
Gradle 初始化阶段主要就是执行 settings.gradle 脚本,构建 Project 对象
我们使用 AndroidStudio 新建一个 Android 项目的时候会自动生成 settings.gradle 文件,内容如下:
rootProject.name = "Demo"
include ':app'
1、指定项目根 Project 的名称
2、使用 include 导入 app 工程
实际上 settings.gradle 对应一个 Settings 对象,include 就是 Settings 对象下的一个方法,它的作用就是引用哪些工程需要加入构建。然后 Gradle 会为每个带有 build.gradle 脚本文件的工程构建一个与之对应的 Project 对象
1、include 扩展
我们可以使用 include + project 方法引用任何位置下的工程,如下:
include ':demo'
project(':demo').projectDir = file('当前工程的绝对路径')
通常我会使用这种方式引用自己写的库进行调试,非常的方便
但有的时候会遇到同时引入了 AAR 和源码的情况,我们可以使用 include + project,结合一些其他的配置,来实现 AAR 和源码的快速切换,具体步骤如下:
//步骤一:在 settings.gradle 中引入源码工程
include ':demo'
project(':demo').projectDir = file('当前工程的绝对路径')
//步骤二:在根 build.gradle 下进行如下配置
allprojects {
configurations.all {
resolutionStrategy {
dependencySubstitution {
substitute module("com.example:demo") with project(':demo')
}
}
}
}
2、Settings
关于 Settings 的所有属性和方法,如下图:
官网提供的文档 传送门
2.配置阶段
Gradle 配置阶段主要就是解析 Project 对象(build.gradle 脚本文件),构建 Task 有向无环图
配置阶段会执行的代码:除 Task 的 Action 中编写的代码都会被执行,不懂 Action 的继续往下看,后面会讲到。如:
1、build.gradle 中的各种语句
2、Task 配置段语句
配置阶段完成后,整个工程的 Task 依赖关系都确定了,我们可以通过 Gradle 对象的 getTaskGraph 方法访问 Task ,对应的类为 TaskExecutionGraph ,关于 TaskExecutionGraph API 文档 传送门
注意: 执行任何 Gradle 命令,在初始化阶段和配置阶段的代码都会被执行
3.执行阶段
Gradle 执行阶段主要就是执行 Task 及其依赖的 Task
二、Gradle 生命周期 Hook 点
引用 joe_H 一张完整的 Gradle 生命周期图,如下
上图对 Gradle 生命周期总结的很到位,我们解析一波:
注意:Gradle 执行脚本文件的时候会生成对应的实例,主要有如下三种对象:
1、Gradle 对象:在项目初始化时构建,全局单例存在,只有这一个对象
2、Project 对象:每一个 build.gradle 都会转换成一个 Project 对象
3、Settings 对象:Seetings.gradle 会转变成一个 Seetings 对象
1、Gradle 在各个阶段都提供了生命周期回调,在添加监听器的时候需要注意:监听器要在生命周期回调之前添加,否则会导致有些回调收不到
2、Gradle 初始化阶段
- 在 settings.gradle 执行完后,会回调 Gradle 对象的 settingsEvaluated 方法
- 在构建所有工程 build.gradle 对应的 Project 对象后,也就是初始化阶段完毕,会回调 Gradle 对象的 projectsLoaded 方法
3、Gradle 配置阶段:
- Gradle 会循环执行每个工程的 build.gradle 脚本文件
- 在执行当前工程 build.gradle 前,会回调 Gradle 对象的 beforeProject 方法和当前 Project 对象的 beforeEvaluate 方法
- 在执行当前工程 build.gradle 后,会回调 Gradle 对象的 afterProject 方法和当前 Project 对象的 afterEvaluate 方法
- 在所有工程的 build.gradle 执行完毕后,会回调 Gradle 对象的 projectsEvaluated 方法
- 在构建 Task 依赖有向无环图后,也就是配置阶段完毕,会回调 TaskExecutionGraph 对象的 whenReady 方法
注意: Gradle 对象的 beforeProject,afterProject 方法和 Project 对象的 beforeEvaluate ,afterEvaluate 方法回调时机是一致的,区别在于:
1、Gradle 对象的 beforeProject,afterProject 方法针对项目下的所有工程,即每个工程的 build.gradle 执行前后都会收到这两个方法的回调
2、 Project 对象的 beforeEvaluate ,afterEvaluate 方法针对当前工程,即当前工程的 build.gradle 执行前后会收到这两个方法的回调
4、执行阶段:
- Gradle 会循环执行 Task 及其依赖的 Task
- 在当前 Task 执行之前,会回调 TaskExecutionGraph 对象的 beforeTask 方法
- 在当前 Task 执行之后,会回调 TaskExecutionGraph 对象的 afterTask 方法
5、当所有的 Task 执行完毕后,会回调 Gradle 对象的 buildFinish 方法
了解了 Gradle 生命周期后,我们就可以根据自己的需求添加 Hook。例如:我们可以打印 Gradle 构建过程中,各个阶段及各个 Task 的耗时
三、打印 Gradle 构建各个阶段及各个任务的耗时
在 settings.gradle 添加如下代码:
//初始化阶段开始时间
long beginOfSetting = System.currentTimeMillis()
//配置阶段开始时间
def beginOfConfig
//配置阶段是否开始了,只执行一次
def configHasBegin = false
//存放每个 build.gradle 执行之前的时间
def beginOfProjectConfig = new HashMap()
//执行阶段开始时间
def beginOfTaskExecute
//初始化阶段执行完毕
gradle.projectsLoaded {
println "初始化总耗时 ${System.currentTimeMillis() - beginOfSetting} ms"
}
//build.gradle 执行前
gradle.beforeProject {Project project ->
if(!configHasBegin){
configHasBegin = true
beginOfConfig = System.currentTimeMillis()
}
beginOfProjectConfig.put(project,System.currentTimeMillis())
}
//build.gradle 执行后
gradle.afterProject {Project project ->
def begin = beginOfProjectConfig.get(project)
println "配置阶段,$project 耗时:${System.currentTimeMillis() - begin} ms"
}
//配置阶段完毕
gradle.taskGraph.whenReady {
println "配置阶段总耗时:${System.currentTimeMillis() - beginOfConfig} ms"
beginOfTaskExecute = System.currentTimeMillis()
}
//执行阶段
gradle.taskGraph.beforeTask {Task task ->
task.doFirst {
task.ext.beginOfTask = System.currentTimeMillis()
}
task.doLast {
println "执行阶段,$task 耗时:${System.currentTimeMillis() - task.ext.beginOfTask} ms"
}
}
//执行阶段完毕
gradle.buildFinished {
println "执行阶段总耗时:${System.currentTimeMillis() - beginOfTaskExecute}"
}
//打印结果如下:
初始化总耗时 33 ms
配置阶段,root project 'myapp' 耗时:83 ms
配置阶段,project ':app' 耗时:12 ms
配置阶段,project ':base_module' 耗时:16 ms
配置阶段,project ':cockroach' 耗时:6 ms
配置阶段,project ':data_module' 耗时:14 ms
配置阶段,project ':easyPhotos' 耗时:5 ms
配置阶段,project ':hprt_hm_a300' 耗时:10 ms
配置阶段,project ':module_aftersale' 耗时:11 ms
配置阶段,project ':module_approve' 耗时:7 ms
配置阶段,project ':module_color_card' 耗时:22 ms
配置阶段,project ':module_commodity' 耗时:11 ms
配置阶段,project ':module_common' 耗时:18 ms
配置阶段,project ':module_crm' 耗时:13 ms
配置阶段,project ':module_documentary' 耗时:10 ms
配置阶段,project ':module_editionroom' 耗时:10 ms
配置阶段,project ':module_fabric' 耗时:23 ms
配置阶段,project ':module_financial' 耗时:8 ms
配置阶段,project ':module_order' 耗时:6 ms
配置阶段,project ':module_supplier' 耗时:6 ms
配置阶段,project ':module_warehouse' 耗时:10 ms
配置阶段,project ':netlib' 耗时:6 ms
配置阶段,project ':okdownload' 耗时:5 ms
配置阶段,project ':pickerview' 耗时:7 ms
配置阶段,project ':util_lib' 耗时:4 ms
配置阶段总耗时:893 ms
> Task :prepareKotlinBuildScriptModel
执行阶段,task ':prepareKotlinBuildScriptModel' 耗时:0 ms
执行阶段总耗时:5191
本文转载地址: sweetying大佬 juejin.cn/post/698619…