间隔 Google 在 I/O 2013 上首次发布 Android Gradle Plugin(AGP) 0.1 版本,已有十年之久。然而,即使是经验丰富的 Android 开发者,也或许对 Gradle 和 AGP 的运用和深度把握感到困惑。我写过不少的 Gradle/AGP 相关文章,做过线上共享,乃至写了一本书和一本小册子;但平常的沟通中发现对多数人来说仍是难以找到学习的路径,即使花时间也未有明显前进。所以在 AGP 十周年之际,我决定用简略文字记录“为什么我仍是学不会 Gradle/AGP”的一点调查。

这篇文章将回顾 Gradle 的演变,尤其是曩昔的困难,以及最近两三年的改善。终究,我将供给一些学习战略,帮助新手和有经验的工程师更好地把握这个构建体系。

声明:本文章涵盖的均为揭露可获取的资料,首要来自于官方的揭露共享或社区的声音。

Gradle 自身有诸多难点,包括但不限于多变的 DSL、生命周期的细节、兼容性问题多、调试定位和优化难度大等等。全体来看,要完结一个扩展插件,一次性需求把握的概念较多。

I/O 23 暨 AGP 10周年:为什么我还是学不会 Gradle?

(无妨问问神奇的海螺)

但概念多、难点多不是问题,React.js、Jetpack Compose 等等结构的概念也适当杂乱,为什么对咱们来说上手难度就不算大呢?

I/O 23 暨 AGP 10周年:为什么我还是学不会 Gradle?

实际上,不少常见的结构东西,都能在学习初期为开发者快速找到适用场景;而 Gradle 和 AGP 的学习则需求投入许多时间后才干看到效果。关于多数初学者而言,即使你英语不错,看得懂 Gradle 官方的 User Guide,也无法一下找对运用场景,更别提组合相关部件获得最佳实践。而另外一个角度看,咱们或许忘了作为 Android 开发者,这个东西本质上要作用于 Android App 的构建进程中才干发挥出它最大的价值,AGP 的学习被不少人所疏忽。

上述调查引出了本文的两个考虑:

  1. Gradle 的官方文档是零星的常识点,短少了面向初学者的实战教程,也就是 Tutorial 类的文档。
  2. AGP 的揭露 API 与可扩展性存在必定限制。AGP 的方针久远,其首要目的是为了推进 Android 构建生态的全体发展,但为了平衡保护本钱,不或许敞开一切的 API。

Gradle 的文档问题

第一点,文档的问题。“零星”指代了有两个方面:

  1. 不少必要的常识点没有辅导文档:举个例子,咱们都用过 android.buildTypes{...} 的定义,它本质上是 NamedDomainObjectContainer 类和它一系列父类的根底运用。你能找到的是 API 注释文档,但在 User Guide 上找不到辅导性的阐明,例如多个相似 API 的比较,在 Groovy DSL 中的增删查改、Kotlin 中的增删查改、怎么在两个 DSL 之间搬迁和运用等等。Google 查找出来的相关前期参考资料,是 Mr.HAKi 的Gradle Goodness 系列文章,该系列博客中还有许多其他的 API 运用事例。
  2. 文档有小部分从 0 到 1 的内容,例如生命周期,使命根底。而许多其他常见的组件、API 技巧、怎么组合运用多个东西,不行详细、或或许放在犄角角落。综合的阅览体验有些差强人意:你分明好像在哪里见过它,但又想不起来,乃至关键词查找都有些困难。用户缺失了一套自身的学习路线参考。

从这个角度上看,一些知名的 Gradle 系列视频沿用了官方文档的规划思路,并不利于初学者快速上手。当然从常识面上,他们仍然是官方文档的有力补充。

但这儿必须要插一个转机:大部分结构/东西的文档在常识点充足的情况下,仍存在零星、没有先后顺序的问题,背面有其特定原因。关于许多优异的结构开发而言,写好每一个文件里的 API 注释,再加上许多的测验,就是一套谨慎且可被其他开发者自行学习参悟的文档了。而其导出的 API 文档即为中心“文档”,并非要许多事例、辅导性资料才干称之为“文档”,那是如虎添翼的 Tutorial。

这也是为什么不少技能公司、技能产品会招聘特别的技能布道师、技能写作者等职位,辅导性的文档以及开源的 Sample 库房,多数会经他们之手而释出。典型的例子如 Now-In-Android。

短少必定的完好辅导文档,那 Gradle 的文档中剩余最多的就是脚本插件(Script Plugin)的事例。脚本因为 DSL API 的原因,虽然文档上看着很整齐,可一旦需求自己编写二进制插件(即编译后发布的插件,内部包含了一个或多个 Plugin 的完结,通常咱们引用的库都是以二进制插件的方式发布)时,往往却需求原生 API。而前面七八年因为 Groovy 为主的脚本生态,从一些 DSL 中找到对应的原生 API 有些困难——NamedDomainObjectContainer 再次成为该问题的典型事例。通过 Groovy 动态特性完结的查找、增加融为一体的 API,运用者实际上不知道背面到底是用的 create() 仍是 getByName() 或许 named() 等等,这在写 build.gradle 装备时是优势,在真的写二进制插件时是下风。我的调查中,Groovy 放大了普通人想要把握该东西的难度;但关于许多职业先锋而言,熟练的 Groovy 技巧反倒让他们觉得 Gradle 灵活好用,并且直到 K2 发布前都可因 Groovy 让装备阶段的脚本编译速度更快。

终究,因为 Gradle 的产品态度,不会给出太多 Android 生态协同的事例,关于 AGP 可参考下个问题的评论。惋惜因为某些特殊原因,许多监控的 API 也没有放出,乃至咱们看到部分第三方插件都已经在调用私有 API 的情况下,仍然没有这部分问题的阐明。这其间包括了多数揭露的生命周期钩子的废弃(因为 Configuration Cache),对这些揭露 API 的平替也未有完好阐明,有些官方的最新实践需从 Gradle 论坛或 Slack 评论组才干看到。

AGP 的敞开性问题

Gradle 学习曲线陡峭,但“学了许多根底”却做不出来东西,更多是因为短少对生态的了解。Gradle 作为一个基层根底,支撑的不只是 Android,还包括 Java、Kotlin、Scala 等言语生态,以及几乎最巨大的 JVM 后端结构生态,包括 Spring 等等。不难想到关于 Android 开发者而言,了解 Android Gradle Plugin(AGP)和相关编译东西的种种细节,是打包进程的中心一环。

在前期的五六年中,AGP 较少揭露其开发计划和社区发展支撑,也难以找到相关的技能文档。2018、2019 年逐步在一些重要的官方会议中发声,了解第三方插件开发者的痛点并同步其了揭露 API 的建设前进,并于 2021 年的 I/O 会议上完好发布了 AGP 7.0 的相关大改动,包括了文档和 Sample 的支撑。

从 issue tracker 的情况来看,P1/S1 的问题虽然得到了处理,但仍然有许多“次一级”的问题待完善。我个人也在尽力帮助推进新 API 的进程中发现了一些问题,例如:

  1. 揭露的 Artifact API 现在只有十几种,而私有 API 中有多达 200 种。
  2. 揭露的字节码修正 Artifact API 和私有完结有所不同,当存在多个转换使命时会出现缓存失效。

基于上述客观内容,开发者学习 AGP 没有一条直观的路径。许多文章在介绍 AGP 时直接罗列其使命列表、逐一剖析,亦是百般无奈的选择。但这种方式的学习效果或许…不算太好。既然没有文档和架构规划,体系学习就是要靠阅览源码,了解全体规划范式。阅览的进程需求带着多个平常碰到的单点问题去考虑,例如 AGP 的使命注册流程有什么范式,新 Artifact API 背面的链式结构怎么帮助数据的传递和终究 API 的暴露等等。而有这些问题的条件是,你作为效能专项的开发者、或把自己放到这个位置去考虑,写出一个又一个或许并不契合 Gradle 和 AGP “标准” 的插件,从中看到问题、阅览源码、处理问题,终究获得成长。编写的这类插件我称之为“Android 生态的协同插件”,和一些平台无关的插件有大相径庭(例如剖析 Gradle 依靠的插件)。

大多数人没办法或没时机阅历上述进程,所以市场上就只有两类人:初学者和专家。而中间的几个层级断档明显。这也反应在了主题曝光的分配上,曩昔十年 AGP 的主题共享不少是夹杂在 AS 或 Android 开发东西更新傍边。直到最近,AGP 终于在文档区拥有了自己的一个子页卡(独立导航)。

I/O 23 暨 AGP 10周年:为什么我还是学不会 Gradle?

近年改善与学习战略引荐

尽管上述种种问题曾经使得 Gradle 的学习和运用变得困难,可是在曩昔的两三年里,有一些严重的改善:

  1. Kotlin 成为默许的脚本言语:Kotlin 言语现在是 Gradle 的默许脚本言语。关于 Android 开发者来说,这是个好消息,因为他们能够运用同一种言语来完结运用开发和构建脚本的开发。相较于 Groovy,Kotlin 更简单上手。

  2. AGP 的新特性:AGP 跟进了 Gradle 的 Lazy Property、Configuration Cache、Work Executor 等特性;供给了真正的揭露 API,包括完好面向开发者的 Variant 生命周期,Artifact 暴露机制,以及相关的 Sample 阐明。开发者能够更简单地扩展 AGP 的功用。

  3. 编译速度的提高:Google、JetBrains 和 Gradle 三家公司的合作共建,例如:

    1. 各类缓存机制、并行执行机制、延迟注册机制被 AGP 引进。
    2. Kotlin 的编译速度不断地提高。
    3. Google 开发的 KSP 符号处理东西,引进到各类 Android、Kotlin 的开发东西中,大幅提高了符号处理器的功率。
    4. Android Studio 的各项 Gradle 周边功用支撑,包括 AGP API 搬迁、功能剖析东西等。
    5. 未来新的 Kotlin 编译器 K2 和完好的编译器插件生态东西链,会带来更极致的功能提高。

基于上述的改善,如果让我为新手和中高级工程师给点学习建议,我认为是:

  1. 针对新手的战略

    • 1.1 先学习 Kotlin 和 Gradle 的根底概念,如 DSL,项目的安排结构,使命机制等。
    • 1.2 再学习常见插件及其 Extension 的运用,例如 Android、Java、Kotlin、Maven 发布等。
    • 1.3 终究逐渐深化一些进阶论题,如简单的脚本修正、简单的使命编写、根底的编译问题定位等。
    • 1.4 我安排编写的《KOGE》开源小册,涵盖了上述的大部分根底概念,欢迎阅览&提出建议&参加编写。
  2. 针对中高级工程师的战略

    • 2.1 围绕“增强 Android Gradle Plugin 功用”,学习编写与 Android 生态协同的插件。这是提高编译构建全方面素质的一个重要门槛,需求坚决跨过。由方针驱动,发现问题、阅览源码、处理问题,循环这个进程,不断提高对生态协同插件的认知。
    • 2.2 将插件技能运用到出产的方方面面,如资源修正、源码修正、字节码修正等,不只学习相关编译东西链,还要从多个角度考虑问题,结合编译时和运行时的计划,优势互补。
    • 2.3 学习更多 AGP 的内核思维和架构规划,优化上述多种插件计划,将其间优异的架构思路带到 App 的效能架构中,为团队带来“低本钱低编译耗时、高功能高可保护性”的开发体验。
    • 关于想提速学习的朋友,可入手我的新书《Android 构建与架构实战》,体系学习 Gradle 插件开发与 AGP 的内核规划。

总的来说,尽管前期 Gradle 和 AGP 的学习进程或许令人望而生畏,可是随着最近的改善和正确的学习战略,开发者能够更好地把握这个强大的构建东西,以提高出产功率和代码质量。

喜欢这篇文章的话无妨点个赞~ 也欢迎关注公众号专栏 “Android高效开发”。