二十八、安卓工程师必须了解的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

Task之间存在依赖关系

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

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

Gradle自定义方法

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

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

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

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

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

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

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

project

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

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

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

举个很实用的例子:

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

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

subprojects{} 实际上是在对所有的子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插件,

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

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

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

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

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

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

总结

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

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

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

相关推荐
万叶学编程3 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
前端李易安4 小时前
Web常见的攻击方式及防御方法
前端
PythonFun5 小时前
Python技巧:如何避免数据输入类型错误
前端·python
知否技术5 小时前
为什么nodejs成为后端开发者的新宠?
前端·后端·node.js
hakesashou5 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆5 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF5 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi5 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi5 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript