13.6.10.2 Kotlin 1.4.20 的新变化
8 分钟阅读
13.6.10.2 Kotlin 1.4.20 的新变化
阅读 Kotlin 1.4.20 的发行说明,涵盖新的语言特性、Kotlin Multiplatform、JVM、Native、JS 的更新,以及对 Gradle 和 Maven 构建工具的支持。
Kotlin 1.4.20 提供了若干新的实验性特性,并对现有特性(包括 1.4.0 中新增的特性)进行了修复和改进。
你也可以在这篇博客文章中通过更多示例了解新特性。
提示: 关于 Kotlin 发布周期的信息,请参阅 Kotlin 发布流程。
Kotlin/JVM
Kotlin/JVM 的改进旨在使其跟上现代 Java 版本的特性:
Java 15 目标
现在 Java 15 可以作为 Kotlin/JVM 的目标使用。
invokedynamic 字符串拼接
警告:
invokedynamic字符串拼接是实验性的。它可能随时被移除或更改。需要选择启用(详见下文)。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
Kotlin 1.4.20 可以在面向 JVM 9+ 的目标时把字符串拼接编译为动态调用,从而提升性能。
目前,该特性是实验性的,覆盖以下情况:
- 运算符形式(
a + b)、显式形式(a.plus(b))和引用形式((a::plus)(b))的String.plus。 - 内联类和 data 类上的
toString。 - 字符串模板,但只有一个非常量实参的除外(参见 KT-42457)。
要启用 invokedynamic 字符串拼接,请添加 -Xstring-concat 编译器选项,并使用以下值之一:
indy-with-constants,对字符串使用 StringConcatFactory.makeConcatWithConstants() 执行invokedynamic拼接。indy,对字符串使用 StringConcatFactory.makeConcat() 执行invokedynamic拼接。inline,切换回通过StringBuilder.append()的经典拼接方式。
Kotlin/JS
Kotlin/JS 一直在快速演进,在 1.4.20 中可以找到许多实验性特性和改进:
Gradle DSL 的变化
Kotlin/JS 的 Gradle DSL 获得了若干更新,简化了项目设置和自定义。这包括 webpack 配置调整、对自动生成的 package.json 文件的修改,以及对传递依赖的更佳控制。
webpack 配置的单一入口
浏览器目标新增了一个配置块 commonWebpackConfig。在其中,你可以从一个单一入口调整通用设置,而无需为 webpackTask、runTask 和 testTask 重复配置。
要让这三个任务默认启用 CSS 支持,请在项目的 build.gradle(.kts) 中添加以下代码片段:
| |
进一步了解配置 webpack 打包。
从 Gradle 自定义 package.json
为了更好地控制 Kotlin/JS 的包管理和分发,你现在可以通过 Gradle DSL 向项目文件 package.json 添加属性。
要向 package.json 添加自定义字段,请在编译的 packageJson 块中使用 customField 函数:
| |
进一步了解 package.json 自定义。
选择性的 yarn 依赖解析
警告: 对选择性 yarn 依赖解析的支持是实验性的。它可能随时被移除或更改。请仅将其用于评估目的。我们非常欢迎你在 Youtrack 上提供反馈。
Kotlin 1.4.20 提供了一种配置 Yarn 选择性依赖解析的方式 —— 这是一种覆盖你所依赖包之依赖的机制。
你可以通过 Gradle 中 YarnPlugin 内部的 YarnRootExtension 来使用它。要影响项目中某个包解析出的版本,请使用 resolution 函数,并传入包名选择器(按 Yarn 的规定)以及它应解析到的版本。
| |
在这里,你所依赖的、需要 react 的_所有_ npm 依赖都会得到版本 16.0.0,而 processor 的依赖 decamelize 会得到版本 3.0.0。
禁用细粒度工作区
警告: 禁用细粒度工作区是实验性的。它可能随时被移除或更改。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
为加快构建速度,Kotlin/JS Gradle 插件只安装特定 Gradle 任务所需的依赖。例如,webpack-dev-server 包只在你执行某个 *Run 任务时才会安装,而在执行 assemble 任务时不会。当你并行运行多个 Gradle 进程时,这种行为可能带来问题。当依赖需求冲突时,两次安装 npm 包可能会导致错误。
为解决这个问题,Kotlin 1.4.20 提供了禁用这些所谓_细粒度工作区_的选项。该特性目前可通过 Gradle 中 YarnPlugin 内部的 YarnRootExtension 使用。要使用它,请在 build.gradle.kts 文件中添加以下代码片段:
| |
新的向导模板
为了让你在创建项目时有更方便的自定义方式,Kotlin 的项目向导为 Kotlin/JS 应用带来了新模板:
- Browser Application —— 一个在浏览器中运行的最小 Kotlin/JS Gradle 项目。
- React Application —— 一个使用相应
kotlin-wrappers的 React 应用。它提供了启用样式表、导航组件或状态容器集成的选项。 - Node.js Application —— 一个在 Node.js 运行时中运行的最小项目。它提供了直接包含实验性
kotlinx-nodejs包的选项。
使用 IR 编译器忽略编译错误
警告:_忽略编译错误_模式是实验性的。它可能随时被移除或更改。需要选择启用(详见下文)。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
Kotlin/JS 的 IR 编译器带来了一个新的实验性模式 —— 带错误的编译。在该模式下,即使代码包含错误你也能运行它,例如当整个应用还没准备好、但你想先尝试某些东西时。
该模式有两种容错策略:
SEMANTIC:编译器会接受语法正确但在语义上不合理的代码,例如val x: String = 3。SYNTAX:编译器会接受任何代码,即使其中包含语法错误。
要允许带错误编译,请添加 -Xerror-tolerance-policy= 编译器选项,并传入上面列出的值之一。
Kotlin/Native
Kotlin/Native 在 1.4.20 中的重点是性能和打磨现有特性。以下是值得注意的改进:
逃逸分析
警告: 逃逸分析机制是实验性的。它可能随时被移除或更改。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
Kotlin/Native 获得了新的逃逸分析机制的原型。它通过在栈上而不是堆上分配某些对象来提升运行时性能。在我们的基准测试中,该机制平均带来 10% 的性能提升,我们会继续改进它以进一步加速程序。
逃逸分析在 release 构建(使用 -opt 编译器选项)中作为一个单独的编译阶段运行。
如果你想禁用逃逸分析阶段,请使用 -Xdisable-phases=EscapeAnalysis 编译器选项。
性能改进与缺陷修复
Kotlin/Native 在多个组件中获得了性能改进和缺陷修复,包括 1.4.0 中新增的组件,例如代码共享机制。
选择启用包装 Objective-C 异常
警告: Objective-C 异常包装机制是实验性的。它可能随时被移除或更改。需要选择启用(详见下文)。请仅将其用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
Kotlin/Native 现在可以在运行时处理从 Objective-C 代码抛出的异常,以避免程序崩溃。
你可以选择启用把 NSException 包装为 ForeignException 类型的 Kotlin 异常。它们持有对原始 NSException 的引用。这让你可以获取根本原因的相关信息并正确处理它。
要启用 Objective-C 异常包装,请在 cinterop 调用中指定 -Xforeign-exception-mode objc-wrap 选项,或向 .def 文件添加 foreignExceptionMode = objc-wrap 属性。如果你使用 CocoaPods 集成,请在依赖的 pod {} 构建脚本块中指定该选项,如下所示:
| |
默认行为保持不变:当 Objective-C 代码抛出异常时,程序会终止。
CocoaPods 插件的改进
Kotlin 1.4.20 继续为 CocoaPods 集成带来一系列改进。具体来说,你可以试用以下新特性:
改进的任务执行
CocoaPods 插件的任务执行流程得到了改进。例如,如果你新增一个 CocoaPods 依赖,已有依赖不会被重新构建。添加额外的目标也不会影响为已有目标重新构建依赖。
扩展的 DSL
向 Kotlin 项目添加 CocoaPods 依赖的 DSL 获得了新的能力。
除了本地 Pod 和来自 CocoaPods 仓库的 Pod,你还可以添加对以下类型库的依赖:
- 来自自定义 spec 仓库的库。
- 来自 Git 仓库的远程库。
- 来自压缩包的库(也可以通过任意 HTTP 地址获取)。
- 静态库。
- 带自定义 cinterop 选项的库。
进一步了解在 Kotlin 项目中添加 CocoaPods 依赖。示例请参阅使用 CocoaPods 的 Kotlin 示例。
更新后的 Xcode 集成
为了与 Xcode 正确配合,Kotlin 需要对 Podfile 做一些修改:
- 如果你的 Kotlin Pod 有任何 Git、HTTP 或 specRepo Pod 依赖,你也应在 Podfile 中指定它。
- 当你添加来自自定义 spec 的库时,还应把 spec 的位置写在 Podfile 的开头。
现在集成错误在 IDEA 中会有详细的描述。因此如果你的 Podfile 有问题,你会立即知道如何修复。
进一步了解创建 Kotlin pod。
支持 Xcode 12 库
我们添加了对 Xcode 12 提供的库的支持。现在你可以在 Kotlin 代码中使用它们。
Kotlin Multiplatform
更新多平台库发布产物的结构
从 Kotlin 1.4.20 开始,不再有单独的 metadata 发布产物。metadata 产物现在被包含在代表整个库的_根_发布产物中,当把它作为依赖添加到公共源集时,会自动解析为相应的平台特有产物。
进一步了解发布多平台库。
与早期版本的兼容性
这一结构变化破坏了具有分层项目结构的项目之间的兼容性。如果一个多平台项目和它所依赖的库都具有分层项目结构,那么你需要同时把它们更新到 Kotlin 1.4.20 或更高版本。用 Kotlin 1.4.20 发布的库无法在更早版本发布的项目中使用。
不使用分层项目结构的项目和库仍然保持兼容。
标准库
Kotlin 1.4.20 的标准库提供了用于处理文件的新扩展,以及更好的性能。
java.nio.file.Path 的扩展
警告:
java.nio.file.Path的扩展是实验性的。它们可能随时被移除或更改。需要选择启用(详见下文)。请仅将它们用于评估目的。我们非常欢迎你在 YouTrack 上提供反馈。
现在标准库为 java.nio.file.Path 提供了实验性扩展。以符合 Kotlin 习惯的方式使用现代 JVM 文件 API,现在与使用 kotlin.io 包中的 java.io.File 扩展类似。
| |
这些扩展位于 kotlin-stdlib-jdk7 模块的 kotlin.io.path 包中。要使用这些扩展,请选择启用实验性注解 @ExperimentalPathApi。
改进 String.replace 函数的性能
String.replace() 的新实现加快了函数执行速度。区分大小写的变体使用基于 indexOf 的手动替换循环,而不区分大小写的变体使用正则表达式匹配。
Kotlin Android Extensions
在 1.4.20 中,Kotlin Android Extensions 插件被弃用,Parcelable 实现生成器移到单独的插件中。
弃用合成视图
_合成视图_在不久前由 Kotlin Android Extensions 插件引入,用于简化与 UI 元素的交互并减少样板代码。现在 Google 提供了实现同样功能的原生机制 —— Android Jetpack 的视图绑定,因此我们弃用合成视图并推荐使用它。
我们从 kotlin-android-extensions 中提取出 Parcelable 实现生成器,并对其余部分(合成视图)启动弃用周期。目前它们仍可工作,但会给出弃用警告。将来你需要把项目切换到其他方案。以下指南将帮助你从合成视图迁移到视图绑定。
Parcelable 实现生成器的新插件
Parcelable 实现生成器现在位于新的 kotlin-parcelize 插件中。请应用该插件而不是 kotlin-android-extensions。
kotlin-parcelize和kotlin-android-extensions不能同时应用在同一个模块中。
@Parcelize 注解已移到 kotlinx.parcelize 包中。
在 Android 文档中进一步了解 Parcelable 实现生成器。