安卓工程师必须了解的Gradle知识

概述

Android中使用的编译工具就是 gradle,通常我们使用工程默认生成的 build.gradle就能满足基本需求。但是涉及到复杂的工程结构设计,更优雅的配置写法,这就要求我们对gradle有更深的了解。

首先以下概念是必须要掌握的。

Gradle的构建生命周期

一个安卓项目,从源代码 java  和  资源文件  到最终产物 apk,中间有很多过程,大概可以分为三个大步骤。

  1. 初始化(Initialization):在这一阶段,Gradle 将加载项目的构建配置文件(build.gradle)并创建 Gradle 构建对象。它会解析项目的结构、依赖关系和其他配置,并准备构建过程所需的资源和插件。

  2. 配置(Configuration):在这一阶段,Gradle 将根据初始化阶段中加载的构建配置文件来配置项目的构建。它会执行各个模块的配置任务,解析依赖关系,确定编译选项,处理资源文件,应用插件等。这个阶段主要是确定构建的行为和内容,即告诉 Gradle 应该如何构建项目。

  3. 执行(Execution):在这一阶段,Gradle 将根据配置阶段中确定的构建行为来执行实际的构建任务。它会按照指定的顺序执行各个任务,如编译源代码、处理资源文件、运行单元测试、打包 APK 等。这个阶段是构建过程的实际执行阶段,Gradle 会根据配置和任务之间的依赖关系来自动执行所需的任务。

Task

Task 任务,是gradle工作的基本单元。gradle执行编译动作,都是通过一个个task来进行的.

自定义task

dca7d4b4a1042fbad4d35e9fd062d845.jpeg

Task之间存在依赖关系

指定依赖关系有很多种方式,下图是其中一种最简单的。075054401711d5cc68e1e64718d9613a.jpeg

Gradle的构建生命周期中, 配置阶段 会将 所有task的依赖关系确定下来。

Gradle自定义方法

d3d02bb653d8e05541d733b7bf83372f.jpeg

利用def 关键字可以定义一个 方法,写法和java完全类似。并且可以在task中 使用此方法。

利用系统提供的Task构建自己的task

以下就是  创建了我们自己的 copy 任务,并且继承了 系统自带的 Copy任务。0081d4a000b4a0969bc7df8d630815f0.jpeg

比如我们现有的目录结构是:

1f88849d36504599bf1587056baf0909.jpeg

执行完任务之后,目录结构如下:

d655968a97010794099b5b49b9ea57e4.jpeg

我们自定义copy任务的作用就是,将 src内的所有文件,原样拷贝到 dest目录。

至于这里具体有多少个系统的 type 供我们选择,就需要去gradle的官网阅读文档,而且每一个 gradle版本都会有所不同。

project

一个安卓工程,在 gradle作用下,会生成一个 rootProject对象。而 工程下的每一个module,都会是一个Project。

比如下图中,我们的整个工程就是一个 RootProject,其余每一个module都是 Project。

870f28b5b6bcfd04948e9403f65c9164.jpeg

我们可以在 rootProject下统筹管理所有的子project,也就是说,我们能做到 在 根目录的build.gradle中,一次性管理所有 module中的依赖配置。

举个很实用的例子:

我们的项目经过长时间的迭代,会引入很多第三方库,而且有的第三方库会有同一个依赖库的版本的冲突,造成编译失败。常用的解决方式是,在出问题的 module 的 build.gradle中强行指定某个 依赖库的版本。

d4e88fc87f0c32fa6528b4bdecb2eba7.jpeg

但是这种是属于特例,如果这种特例写的太多,我们自己多个module之间的特例也有可能形成冲突。所以最好的办法,就是在 根目录的 build.gradle 中进行统筹管理这些特例。比如下图:

32d4b045e44244b498327f30dc57aeba.jpegsubprojects{} 实际上是在对所有的子module进行遍历。

project.configurations.all{} 则是对一个module中的所有配置进行遍历

resolutionStrategy.eachDependency{} 又是在对一个配置中的所有依赖进行遍历。

经过了三重遍历,最终得到了每个module的每一个依赖配置。

最终,通过group和name,锁定一个依赖,并通过 details.useVersion() 来指定统一的版本号。

这种写法,比在每一个module中进行分别强制指定依赖版本要好得多。

但是仍有一个缺点,那就是 AndroidStudio无法提供代码提示,上图中的${cfgs.androidSupportVersion} 全部都要手动输入或者拷贝。

buildSrc

buildSrc是 编写 gradle插件的其中一种方式,我们在安卓工程中,与app平级,创建一个 buildSrc目录,它是 一个特殊的module,它内部的所有代码,都会转化成gradle插件内容。

buildSrc是解决上面的缺点一个可靠的方式。

在 buildSrc中创建一个 build.gradle.kts文件,并添加 kotlin插件,

12eef8fc254aff57a874caf9ae7a13ac.jpeg

当然,为了编译通过,我们还要引入jcenter仓库。

创建 buildSrc/src/main/java目录,并在其中新建 Dependencies.kt,并添加两个类。8c3279fd96a12dc30871c7f61518f791.jpeg

Version类中指定所有可能使用到的配置版本。207ade87f166b4ba148b66cc34aab8bb.jpeg

Deps类中,添加所有依赖,如下图,这是kotlin的语法,其中每一个依赖的字符串都引用到了 上面的Version张的变量。a6ed25b972ea94dc26e90f03e99ed5e6.jpeg

然后我们就可以 用如下写法去编写依赖 :

17cb1be870ad18cfbee5e123de8644f6.jpeg

最可贵的是,我们在写出Deps.之后,它会默认带出所有的可用的值。

71239cdb852a415a354aa3d4e6b71ab1.jpeg

总结

Task是gradle工作的基本单元,每次编译时,都会在 控制台看到很多gradle task正在执行。

e927d2d0d1ecccd23b5b76b96d3f23a0.jpeg

每一个project都是由多个task组合而成,每个 module 都包含一个build.gradle,每个build.gradle都会被gradle编译成 project字节码,build.gradle中的所有逻辑,都映射成了project字节码的实现逻辑。

最后buildSrc是我们解决 编写 build内容没有代码提示的 简单有效的办法。

作者:拳布离手
链接:https://juejin.cn/post/7307857584882221094

关注我获取更多知识或者投稿

ff4c40e7a6b39d5e49b3dc2968c34a89.jpeg

addb340d0e0216d04cbc84cd58f0c303.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值