0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Gradle入门知识之Gradle详解

jf_78858299 来源:小余的自习室 作者:小余的自习室 2023-03-30 10:47 次阅读

前言:

大家回想一下自己第一次接触Gradle是什么时候?

相信大家也都是和我一样,在我们打开第一个AS项目的时候,

发现有很多带gradle字样的文件:setting.gradle, build.gradle,gradle.warpper,以及在gradle文件中各种配置,

这些都是啥wy啊。。

特别对于一些小公司开发人员,因为接触架构层面的机会很少,可能在使用AS几年后都不一定对Gradle有太多深入了解,这是实话,因为笔者就是这么过来的。。

Gradle又是进阶高级开发的必经之路。

好了,接下来进入正题,此系列笔者会由浅入深的方式,带领大家来了解下,Gradle背后究竟有哪些奥秘。

1.Gradle定义:

很多开发喜欢把Gradle简单定义为一种构建工具,和ant,maven等作用类似,

诚然Gradle确实是用来做构建,但是如果简单得把Gradle拿来做构建,就太小看Gradle了.

笔者更愿意将Gradle看做一种编程框架。在这个框架中,你可以做很多ant,maven等常用构建工具做不了的事情,

如将自己的任务task集成到构建生命周期中,完成文件拷贝,脚本编写等操作。

2.Gradle优缺点:

相较早期的构建工具:ant,maven等。

优点如下:

  • 1.使用DSL Grovvy语言来编写: :了解ant的同学应该都知道:ant使用的是xml配置的模式,而Gradle使用的是表达性的Groovy来编写,

    Groovy同时支持面向对象和面向过程进行开发,这个特性让Groovy可以写出一些脚本的任务,这在传统ant,maven上是不可能实现的

  • 2.基于java虚拟机: :Groovy是基于jvm的语言,groovy文件编译后其实就是class文件,和我们的java一样。

所以在gradle构建过程中,我们完全可以使用java/kotlin去编写我们的构建任务以及脚本,极大的降低我们学习的成本。

  • 3.Gradle自定义task :可以构建自己的任务,然后挂接到gradle构建生命周期中去,这在ant,maven上也是不可能实现的,
  • 4.扩展性好 :gradle将关键配置扔给我们开发者,开发者配置好任务后,无需关心gradle是如何构建的。
  • 5.支持增量更新 :增量更新可以大大加快我们的编译速度

关于Groovy的语法篇:可以参考这篇文章:

Gradle筑基篇(二)-groovy语法详解

缺点:

用过gradle都知道,低版本gradle的项目在高版本的gradle中经常出现很多莫名其妙的错误,向后兼容性较差。

3.Gradle工程结构:

gradle标准工程代码如下

├── moduleA
│   └── build.gradle
├── moduleB
│   └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
├── local.properties
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
  • 1.build.gradle:可以理解为一个Project脚本,Project脚本中有自己的任务,最外层的Project为rootProject
  • 2.settings.gradle:主要用来配置我们项目中需要用到的模块。用include关键字给包裹进
  • 3.gradle.properties:这个文件主要是设置一些全局变量,包括jvm运行以及自定义的一些全局参数
  • 4.local.properties:这个文件主要配置一些本地的sdk和ndk版本信息以及路径
  • 5.gradle-wrapper.jar:负责自动下载Gradle脚本运行环境
  • 6.gradle-wrapper.properties:用来配置当前使用的Gradle的版本以及存储的路径
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionBase + distributionPath:指定Gradle安装路径;
zipStoreBase + zipStorePath:指定Gradle安装包的存储路径;
distributionUrl:Gradle版本的下载地址。

注意这里如果将bin改为all,则可以查看当前Gradle的源码信息。

  • 7.gradlew和gradlew.bat:用来执行构建任务的脚本,可以在命令行使用gradlew xxxTask

4.Gradle生命周期

Gradle作为新兴的构建工具,其内部也有自己的生命周期阶段,每个阶段做的事情都层次分明,

了解Gradle生命周期,才能很好的使用我们的Gradle工具。

1.初始化阶段

做了哪些事情?:

  • 1.初始化Setting.gradle文件,获取setting实例,
  • 2.执行setting中的脚本,根据include字段,创建对应的project实例
  • 3.设置构建需要的环境

注意:初始化阶段执行任何任务都会执行一次。

Project实例关系如下:

图片

gradleproject树.png

2.配置阶段

  • 1.下载所有插件和构建脚本依赖项
  • 2.执行build.gradle文件中的脚本信息
  • 3.实现task任务的拓扑图,这个图是一个有向无环图,防止任务执行进入死循环。

注意:配置阶段执行任何任务都会执行一次。

3.执行阶段

执行阶段就是根据当前task拓扑图进行执行task任务。

需要注意以下几点:

  • 1.在项目中配置的doLast,doFirst操作,都会在任务执行阶段执行,而不会在配置阶段执行,

    而如果任务需要执行,需要挂接到gradle执行生命周期中,笔者开始接触gradle时就踩过这个坑。。这块后面讲解task的时候在来具体讲解

  • 2.前面也说了初始化阶段和配置阶段在每个任务执行前都会执行,所以 不要在前两个阶段进行一些耗时的操作 ,这样可能每次编译执行你都会崩溃的

5.Gradle生命周期监听:

要查找Gradle是如何监听生命周期,可以到Gradle源码中看看:

  • 1.监听初始化阶段

    初始化阶段主要用来初始化Setting.gradle文件,获取setting实例,创建Project实例等,所以其可用下面代码监听:

//开始初始化Setting.gradle前
this.gradle.beforeSettings {
    println "beforeSettings"
}
//Setting.gradle配置完毕后,创建了setting实例
this.gradle.settingsEvaluated {
    println "settingsEvaluated"
}
//执行解析Setting.gradle文件后,创建了project实例列表
this.gradle.projectsLoaded {
    println "projectsLoaded"
}
  • 2.监听配置阶段

2.1:监听当前project的配置阶段前后:

Project源码中可以看到:

/**
 * Adds an action to execute immediately before this project is evaluated.
 *
 * @param action the action to execute.
 */
void beforeEvaluate(Action? action);

/**
 * Adds an action to execute immediately after this project is evaluated.
 *
 * @param action the action to execute.
 */
void afterEvaluate(Action? action);

/**
 * Adds a closure to be called immediately before this project is evaluated. The project is passed to the closure
 * as a parameter.
 *
 * @param closure The closure to call.
 */
void beforeEvaluate(Closure closure);

/**
 * Adds a closure to be called immediately after this project has been evaluated. The project is passed to the
 * closure as a parameter. Such a listener gets notified when the build file belonging to this project has been
 * executed. A parent project may for example add such a listener to its child project. Such a listener can further
 * configure those child projects based on the state of the child projects after their build files have been
 * run.
 *
 * @param closure The closure to call.
 */
void afterEvaluate(Closure closure);

看这两个方法的说明就是用来监听配置阶段,传入的是一个Action或者传入一个闭包,闭包的代理为当前Project

使用方式如下

//监听project被配置前
this.beforeEvaluate {Project project ->
    println "${project.name} :beforeEvaluate"
}
//监听project被配置后
this.afterEvaluate {Project project ->
    println "${project.name}:afterEvaluate"
}

注意:这个监听只是针对当前Project的配置阶段而不是所有Project的配置

你也可以使用:

this.project.beforeEvaluate
this.project.afterEvaluate

那么有没有可以监听所有Project的配置阶段的api呢?安排

2.2:监听每个Project的配置前后:

使用this.gradle的内部方法,因为gradle是相对于整个工程作为作用域

//监听所有的Project的被配置前
this.gradle.beforeProject {Project project ->
    println "${project.name}:beforeProject"
}
//监听所有的Project的被配置后
this.gradle.afterProject {Project project ->
    println "${project.name}:afterProject"
}

编译下看看:

> Configure project :
gradle_source_plugin:afterProject

> Configure project :app
app:beforeProject
do app evaluating
app:afterProject

> Configure project :application
application:beforeProject
do application evaluating
application:afterProject

看到当前工程所有的project都调用了一次beforeProject和afterProject

那有同学又要问了,有没有监听整个project配置阶段的:当然有

2.3:监听全部project配置阶段的前后

this.gradle.projectsEvaluated {
    println "all projectsEvaluated"
}

这个闭包可以监听整个项目的配置完毕后的事件

配置阶段还有一些监听如下:

2.4:监听任务的添加操作

this.project.tasks.whenTaskAdded {Task task->
    println "${task.name}:whenTaskAdded"
}

2.5:监听任务拓扑图的执行

//task拓扑图构造完毕
this.gradle.taskGraph.whenReady {TaskExecutionGraph graph->
    println "taskGraph:->"+graph
}

监听拓扑图完毕后其实才是真正的配置阶段完毕 ,瞧瞧源码:

在BasePlugin中:

threadRecorder.record(
        ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
        project.getPath(),
        null,
        this::configureProject);

threadRecorder.record(
        ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
        project.getPath(),
        null,
        this::configureExtension);

threadRecorder.record(
        ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
        project.getPath(),
        null,
        this::createTasks);

看到配置阶段最后一步才是创建Task,所以可以使用this.gradle.taskGraph.whenReady监听整个配置阶段的结束

  • 3.监听执行阶段

3.1:监听任务执行:

gradle.taskGraph.beforeTask { Task task ->
    println "${task.name}:beforeTask"
}
gradle.taskGraph.afterTask {Task task ->
    println "${task.name}:afterTask"
}
执行下面任务:
task clean(type: Delete) {
    doFirst {
        println 'clean:doFirst'
    }
    doLast {
        println 'clean:doLast'
    }
    delete rootProject.buildDir
}
结果:
> Task :clean
clean:beforeTask
clean:doFirst
clean:doLast
clean:afterTask

可以看到在task执行前后调用了监听中的方法

3.2:监听执行任务阶段开始

其实可以使用配置阶段的this.gradle.taskGraph.whenReady,这个就是所有project配置完毕,且生成了task拓扑图

下一步就是开始执行任务了

3.3:监听执行任务阶段结束

this.gradle.buildFinished {}

这个可以监听所有任务执行完毕后事件回调:

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • DSL
    DSL
    +关注

    关注

    2

    文章

    57

    浏览量

    38199
  • AS
    AS
    +关注

    关注

    0

    文章

    27

    浏览量

    25979
  • gradle
    +关注

    关注

    0

    文章

    26

    浏览量

    662
收藏 人收藏

    评论

    相关推荐

    gradle安装与配置unity

    Gradle是一种用于构建和自动化构建过程的强大工具,而Unity则是一款跨平台的游戏引擎。在Unity项目中使用Gradle可以帮助我们更方便地管理和构建项目,同时能够提供更高的自定义能力和稳定性
    的头像 发表于 12-07 14:48 754次阅读

    Android Studio与Gradle深入

    小语言规范用来处理一个特定的事情(大多情况下是配置)。Android 的插件的 DSL 文档在 Android Gradle DSL有说明。  理解了以上基础之后,你就会知其然,知其所以然了。  以上知识
    发表于 08-31 17:58

    Gradle for Android

    Gradle for Android
    发表于 07-16 15:50

    Gradle的依赖缓存损坏了怎么解决?

    Gradle的依赖缓存被损坏怎么办
    发表于 03-21 10:22

    请问OpenHarmony鸿蒙demo gradle报错怎么解决?

    鸿蒙demo gradle报错怎么解决build.gradle:4: Could not find method ohos() for arguments
    发表于 04-01 11:27

    DevEco Studio自动配置gradle的方法分享

    方法①在项目右键 Find in Path输入gradle-5.4.1-all.zip方法②下载gradle-5.4.1-all.zip解压至不要含有中文名称的目录比如我解压后的路径是D
    发表于 06-09 10:26

    快速入门Gradle的方法

    我们前面的Gradle是一门基于Groov的DSL,可能很多童鞋就是因为你是这个Gradle的迷,第一觉得Gradle是一门独立的语言呀,如果想进入歧途了,我一开始也是这么迷糊的,当你了解之后,你就可以这么理解
    的头像 发表于 04-08 10:56 1015次阅读
    快速<b class='flag-5'>入门</b><b class='flag-5'>Gradle</b>的方法

    Gradle入门知识Gradle详解(下)

    大家回想一下自己第一次接触`Gradle`是什么时候? 相信大家也都是和我一样,在我们打开第一个AS项目的时候, 发现有很多带gradle字样的文件:`setting.gradle, build.
    的头像 发表于 03-30 10:51 654次阅读
    <b class='flag-5'>Gradle</b><b class='flag-5'>入门</b><b class='flag-5'>知识</b>之<b class='flag-5'>Gradle</b><b class='flag-5'>详解</b>(下)

    Gradle入门知识Gradle语法1

    很多开发喜欢把`Gradle`简单定义为一种构建工具,和`ant,maven`等作用类似, 诚然Gradle确实是用来做构建,但是如果简单得把Gradle拿来做构建,就太小看Gradle
    的头像 发表于 03-30 10:54 808次阅读
    <b class='flag-5'>Gradle</b><b class='flag-5'>入门</b><b class='flag-5'>知识</b>之<b class='flag-5'>Gradle</b>语法1

    Gradle入门知识Gradle语法2

    很多开发喜欢把`Gradle`简单定义为一种构建工具,和`ant,maven`等作用类似, 诚然Gradle确实是用来做构建,但是如果简单得把Gradle拿来做构建,就太小看Gradle
    的头像 发表于 03-30 10:54 579次阅读

    Gradle入门知识Gradle api解析(上)

    由于Project源码篇幅太长:这里只列出类的部分方法和属性: 我们前面分析过,每个build.gradle对应一个Project,Project在初始过程中会被构建为`树`形结构:
    的头像 发表于 03-30 11:01 2052次阅读
    <b class='flag-5'>Gradle</b><b class='flag-5'>入门</b><b class='flag-5'>知识</b>之<b class='flag-5'>Gradle</b> api解析(上)

    Gradle入门知识Gradle api解析(下)

    由于Project源码篇幅太长:这里只列出类的部分方法和属性: 我们前面分析过,每个build.gradle对应一个Project,Project在初始过程中会被构建为`树`形结构:
    的头像 发表于 03-30 11:05 840次阅读

    Gradle Plugin和AGP的区别1

    Gradle Plugin`和`AGP`的区别? `Gradle Plugin`是`Gradle`构建过程中使用的插件的总称,而`Android Gradle Plugin`是这
    的头像 发表于 03-30 11:48 996次阅读
    <b class='flag-5'>Gradle</b> Plugin和AGP的区别1

    Gradle Plugin和AGP的区别2

    Gradle Plugin`和`AGP`的区别? `Gradle Plugin`是`Gradle`构建过程中使用的插件的总称,而`Android Gradle Plugin`是这
    的头像 发表于 03-30 11:49 911次阅读

    Gradle Plugin和AGP的区别3

    Gradle Plugin`和`AGP`的区别? `Gradle Plugin`是`Gradle`构建过程中使用的插件的总称,而`Android Gradle Plugin`是这
    的头像 发表于 03-30 11:50 961次阅读