Gradle 之一安卓构建流程

2,568 阅读5分钟

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 的所有属性和方法,如下图:

image.png 官网提供的文档 传送门

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 生命周期图,如下

image.png

上图对 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…