全面理解Gradle - 执行时序

853 阅读3分钟
原文链接: blog.csdn.net

什么是Gradle?

一个像 Ant 一样的非常灵活的通用构建工具
一种可切换的, 像 maven 一样的基于合约构建的框架
支持强大的多工程构建
支持强大的依赖管理(基于 ApacheIvy )
支持已有的 maven 和 ivy 仓库
支持传递性依赖管理, 而不需要远程仓库或者 pom.xml 或者 ivy 配置文件
优先支持 Ant 式的任务和构建
基于 groovy 的构建脚本
有丰富的领域模型来描述你的构建

如何学习Gradle?

使用Gradle wrapper

如果你本地安装了Gradle,那么你就可以使用gradle命令来直接构建。如果本地没有安装,那么可以通过gradle wrapper来构建,Linux和MAC使用./gradlew,而Windows上面则使用gradlew,还可以在 gradle/gradle-wrapper.properties 中配置 Gradle 版本。

Gradle脚本的执行时序

Gradle脚本的执行分为三个过程:

  • 初始化 分析有哪些module将要被构建,为每个module创建对应的 project实例。这个时候settings.gradle文件会被解析。

  • 配置:处理所有的模块的 build 脚本,处理依赖,属性等。这个时候每个模块的build.gradle文件会被解析并配置,这个时候会构建整个task的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表)。

  • 执行:根据task链表来执行某一个特定的task,这个task所依赖的其他task都将会被提前执行。

下面我们根据一个实际的例子来详细说明。这里我们仍然采用VirtualAPK这个开源项目来做演示,它的地址是:github.com/didi/Virtua…

我们以它的宿主端为例,宿主端有如下几个模块:
这里写图片描述
其实buildSrc是virtualapk-gradle-plugin,为了便于调试我将其重命名为buildSrc。他们的依赖关系如下:

这里写图片描述

解释一下,app模块依赖CoreLibrary和buildSrc,CoreLibrary又依赖AndroidStub。为了大家更好理解,下面加一下log。

/***** Settings.gradle *****/

println "settings start"
include ':app'
include ':CoreLibrary'
include ':AndroidStub'
println "settings end"
/***** VirtualAPK.gradle *****/

println "virtualapk start"

allprojects {
    repositories {
        mavenCentral()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
println "virtualapk end"
/***** app.gradle *****/

println "app config start"

apply plugin: 'com.android.application'
apply plugin: 'com.didi.virtualapk.host'

dependencies {
    compile project (":CoreLibrary")
}

project.afterEvaluate {
    println "app evaluate start"
    println "app evaluate end"
}

println "app config end"
/***** CoreLibrary.gradle *****/

apply plugin: 'com.android.library'
println "corelib config start"

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'

    provided project(':AndroidStub')
}

apply from: 'upload.gradle'
println "corelib config end"
/***** AndroidStub.gradle *****/

println "androidstub config start"

dependencies {
    compile 'com.android.support:support-annotations:22.2.0'
}

println "androidstub config end"
/***** buildSrc *****/

public class VAHostPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {
        println "VAHostPlugin config start"

        project.afterEvaluate {
            println "VAHostPlugin evaluate start"

            project.android.applicationVariants.each { ApplicationVariant variant ->
                generateDependencies(variant)
                backupHostR(variant)
                backupProguardMapping(variant)
            }
            println "VAHostPlugin evaluate end"

        }

        println "VAHostPlugin config end"

    }
}

现在随便执行一个task,比如./gradlew clean,那么将会输出如下日志,大家对比着日志,应该能明白Gradle脚本的执行顺序了吧。

VirtualAPK renyugang$ ./gradlew clean
settings start
settings end
virtualapk start
virtualapk end
androidstub config start
androidstub config end
Incremental java compilation is an incubating feature.
corelib config start
corelib config end
app config start
VAHostPlugin config start
VAHostPlugin config end
app config end
VAHostPlugin evaluate start
VAHostPlugin evaluate end
app evaluate start
app evaluate end
:clean
:AndroidStub:clean
:CoreLibrary:clean
:app:clean

BUILD SUCCESSFUL

Total time: 12.381 secs

可以看到,Gradle执行的时候遵循如下顺序:
1. 首先解析settings.gradle来获取模块信息,这是初始化阶段;
2. 然后配置每个模块,配置的时候并不会执行task;
3. 配置完了以后,有一个重要的回调project.afterEvaluate,它表示所有的模块都已经配置完了,可以准备执行task了;
4. 执行指定的task。

备注:如果注册了多个project.afterEvaluate回调,那么执行顺序等同于注册顺序。在上面的例子中,由于buildSrc中的回调注册较早,所以它也先执行。

本公众号聚焦于『Android开发前沿、AI技术、职业发展、生活感悟、妹子图』,欢迎大家关注: