| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Room & Kotlin 符号的处理 -> 正文阅读 |
|
[移动开发]Room & Kotlin 符号的处理 |
△ 图片来自 Unsplash 由 Marc Reichelt 提供 Jetpack Room 库在 SQLite 上提供了一个抽象层,能够在没有任何样板代码的情况下,提供编译时验证 SQL 查询的能力。它通过处理代码注解和生成 Java 源代码的方式,实现上述行为。 注解处理器非常强大,但它们会增加构建时间。这对于用 Java 写的代码来说通常是可以接受的,但对于 Kotlin 而言,编译时间消耗会非常明显,这是因为 Kotlin 没有一个内置的注解处理管道。相反,它通过 Kotlin 代码生成了存根 Java 代码来支持注解处理器,然后将其输送到 Java 编译器中进行处理。 由于并不是所有 Kotlin 源代码中的内容都能用 Java 表示,因此有些信息会在这种转换中丢失。同样,Kotlin 是一种多平台语言,但 KAPT 只在面向 Java 字节码的情况下生效。 认识 Kotlin 符号处理随着注解处理器在 Android 上的广泛使用,KAPT 成为了编译时的性能瓶颈。为了解决这个问题,Google Kotlin 编译器团队开始研究一个替代方案,来为 Kotlin 提供一流的注解处理支持。当这个项目诞生之初,我们非常激动,因为它将帮助 Room 更好地支持 Kotlin。从 Room 2.4 开始,它对 KSP 有了实验性的支持,我们发现编译速度提高了 2 倍,特别是在全量编译的情况下。 本文内容重点不在注解的处理、Room 或者 KSP。而在于重点介绍我们在为 Room 添加 KSP 支持时所面临的挑战和所做的权衡。为了理解本文您并不需要了解 Room 或者 KSP,但必须熟悉注解处理。
本篇文章旨在让注解处理器的作者们在为项目添加 KSP 支持前,充分了解需要注意的问题。 Room 工作原理简介Room 的注解处理分为两个步骤。有一些 “Processor” 类,它们遍历用户的代码,验证并提取必要的信息到 “值对象” 中。这些值对象被送到 “Writer” 类中,这些类将它们转换为代码。和其他诸多的注解处理器一样,Room 非常依赖 Auto-Common 与 javax.lang.model 包 (Java 注解处理 API 包) 中频繁引用的类。 为了支持 KSP,我们有三种选择:
选项 C 实际上是不可行的,因为它会对 Java 用户造成严重的干扰。随着 Room 使用数量的增加,这种破坏性的改变是不可能的。在 “A” 和 “B” 两者之间,我们决定选择 “B”,因为处理器具有相当数量的业务逻辑,将其分解并非易事。 认识 X-Processing在 JavaAP 和 KSP 上创建一个通用的抽象并非易事。Kotlin 和 Java 可以互操作,但模式却不相同,例如,Kotlin 中特殊类的类型如 Kotlin 的值类或者 Java 中的静态方法。此外,Java 类中有字段和方法,而 Kotlin 中有属性和函数。 我们决定实现 “Room 需要什么”,而不是尝试去追求完美的抽象。从字面意思来看,在 Room 中找到导入了 遗憾的是, 另一方面,我们需要证明这是可行的。所以我们首先对其做了 原型 设计,一旦验证这是一个合理的选择,我们就用他们自己的测试 逐一重新实现了所有 X 类。 关于我说的实现 “Room 需要什么”,有一个很好的例子,我们可以在关于类的字段 更改 中看到。当 Room 处理一个类的字段时,它总是对其所有的字段感兴趣,包括父类中的字段。所以我们在创建相应的 X-Processing API 时,只添加了获取所有字段的能力。
如果我们正在设计一个通用库,这样可能永远不会通过 API 审查。但因为我们的目标只是 Room,并且它已经有一个与 一旦我们有了基本的 X-Processing API 和它们的测试方法,下一步就是让 Room 来调用这个抽象。这也是 “实现 Room 所需要的东西” 获得良好回报的地方。Room 在 改进 API 可用性保留类似 JavaAP 的 API 并不意味着我们不能改进任何东西。在将 Room 迁移到 X-Processing 之后,我们又实现了一系列的 API 改进。 例如,Room 多次调用
我们把所有的调用放到了 Kotlin contracts 中,这样一来就可以写成:
另一个很好的例子是在一个
最后一个例子,这也可能是我最喜欢的例子之一,就是可分配性。在 JavaAP 中,如果您要检查给定的 TypeMirror 是否可以由另一个 TypeMirror 赋值,则需要调用 Types.isAssignable。
这段代码真的很难读懂,因为您甚至无法猜到它是否验证了类型 1 可以由类型 2 指定,亦或是完全相反的结果。我们已经有一个扩展函数如下:
在 X-Processing 中,我们能够将其转换为
为 X-Processing 实现 KSP 后端这些 X-Processing 接口每个都有自己的测试套件。我们编写它们并非是用来测试 AutoCommon 或者 JavaAP 的,相反,编写它们是为了在有了它们的 KSP 实现时,我们就可以运行测试用例来验证它是否符合 Room 的预期。 由于最初的 X-Processing API 是按照 这样产生了一个新问题。现有的 Room 代码库是为了处理 Java 源代码而写的。当应用是由 Kotlin 编写时,Room 只能识别该 Kotlin 在 Java 存根中的样子。我们决定在 X-Processing 的 KSP 实现中保持类似行为。 例如,Kotlin 中的
为保持相同的行为,KSP 中的
另一个例子与属性有关。Kotlin 属性也可能具有基于其签名的合成
在为 X-Processing 添加 KSP 实现时,最后一个有趣的问题是 API 耦合。这些处理器的 API 经常相互访问,因此如果不实现 需要注意的是,在此阶段我们只在 X-Processing 项目中运行测试,所以即使我们知道测试的内容没问题,我们也无法保证所有的 Room 测试都能通过 (也称之为单元测试 vs 集成测试)。我们需要通过一种方法来使用 KSP 后端运行所有的 Room 测试,“X-Processing-Testing” 就应运而生。 认识 X-Processing-Testing注解处理器的编写包含 20% 的处理器代码和 80% 的测试代码。您需要考虑到各种可能的开发者错误,并确保如实报告错误消息。为了编写这些测试,Room 已经提供一个辅助方法如下:
糟糕的是,Google Compile Testing 仅支持 Java 源代码。为了测试 Kotlin 我们需要另一个库,幸运的是有 Kotlin Compile Testing,它允许我们编写针对 Kotlin 的测试,而且我们为该库贡献了对 KSP 支持。
作为能让 KSP 运行所有测试的最后一步,我们创建了以下测试 API:
这个和原始版本之间的主要区别在于,它同时通过 KSP 和 JavaAP (或 KAPT,取决于来源) 运行测试。因为它多次运行测试且 KSP 和 JavaAP 两者的判断结果不同,因此无法返回单个结果。 因此,我们想到了一个办法:
每次编译后,它都会调用结果断言 (如果没有失败提示,则检查编译是否成功)。我们把每个 Room 测试重构为如下所示:
接下来的事情就很简单了。将每个 Room 的编译测试迁移到新的 API,一旦发现新的 KSP / X-Processing 错误,就会上报,然后实施临时解决方案;这一动作反复进行。由于 KSP 正在大力开发中,我们确实遇到了很多 bug。每一次我们都会上报 bug,从 Room 源链接到它,然后继续前进 (或者进行修复)。每当 KSP 发布之后,我们都会搜索代码库来找到已修复的问题,删除临时解决方案并启动测试。 一旦编译测试覆盖情况较好,我们在下一步就会使用 KSP 运行 Room 的 集成测试。这些是实际的 Android 测试应用,也会在运行时测试其行为。幸运的是,Android 支持 Gradle 变体,因此使用 KSP 和 KAPT 来运行我们 Kotlin 集成测试 便相当容易。 下一步将 KSP 支持添加到 Room 只是第一步。现在,我们需要更新 Room 来使用它。例如,Room 中的所有类型检查都忽略了 同样,即使我们支持 KSP,Room 仍然只生成 Java 代码。这种限制使我们无法添加对某些 Kotlin 特性的支持,比如 Value Classes。希望在将来,我们还能对生成 Kotlin 代码提供一些支持,以便在 Room 中为 Kotlin 提供一流的支持。接下来,也许更多 😃。 我能在我的项目上使用 X-Processing 吗?答案是还不能;至少与您使用任何其他 Jetpack 库的方式不同。如前文所述,我们只实现了 Room 需要的部分。编写一个真正的 Jetpack 库有很大的投入,比如文档、API 稳定性、Codelabs 等,我们无法承担这些工作。话虽如此,Dagger 和 Airbnb (Paris、DeeplinkDispatch) 都开始用 X-Processing 来支持 KSP (并贡献了他们需要的东西🙏)。也许有一天我们会把它从 Room 中分解出来。从技术层面上讲,您仍然可以像使用 Google Maven 库 一样使用它,但是没有 API 保证可以这样做,因此您绝对应该使用 shade 技术。 总结我们为 Room 添加了 KSP 支持,这并非易事但绝对值得。如果您在维护注解处理器,请添加对 KSP 的支持,以提供更好的 Kotlin 开发者体验。 特别感谢 Zac Sweers 和 Eli Hart 审校这篇文章的早期版本,他们同时也是优秀的 KSP 贡献者。 更多资源
欢迎您 点击这里 向我们提交反馈,或分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持! |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 5:46:15- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |