Kotlin
A concise multiplatform language developed by JetBrains
Kotlin 1.4-M2 正式发布!
时光飞逝,今天我们想向您展示 Kotlin 1.4 的一些强大功能,供您预览。 了解 Kotlin 1.4-M2 引入的功能,在 Kotlin 1.4 正式发布之前试用这些功能。
我们向所有试用 Kotlin 1.4 首个预览版的用户表示感谢,感谢大家提供反馈,并帮助使 Kotlin 更出色!
还要感谢已经体验 我们上一篇博文中宣布的 Kotlin 1.4-M2 标准库改进的用户。
在这篇博文中,我们将重点介绍 1.4-M2 中的新功能和主要改进:
- 得益于多平台项目中的分层结构,现在支持在多个目标中共享代码
- 灵活的新 Kotlin 项目向导 使创建和配置不同类型的项目变得简单。
- 面向库作者的新编译器模式——显式 API,有助于创建一致且描述良好的 API。
- Kotlin/Native 支持在 Swift 和 Objective-C 中使用挂起函数。
- Kotlin/JS 改进的 Gradle DSL、开箱即用的 CSS 支持和通用导出注解。
您可以在 变更日志中找到完整的变更列表。 我们要一如既往地感谢外部贡献者。
使用分层项目结构在多个目标中共享代码
借助新的分层项目结构支持,您可以在多平台项目的多个目标中共享代码。
之前,添加到多平台项目中的任何代码都可以放置在平台专用源集中(仅限一个目标,且不能由其他任何平台重用),或放置在通用源集(如 commonMain
或 commonTest
)中,在项目中的所有平台之间共享。 在通用源集中,您只可以使用需要平台专用 actual
实现的 expect
声明调用平台专用的 API。
这使得在所有目标之间共享代码十分容易,但仅在一些目标之间共享代码就不太方便,特别是可能会重用许多通用逻辑和第三方 API 的相似目标。
例如,在以 iOS 为目标的典型多平台项目中,有两个 iOS 相关的目标:一个面向 iOS ARM64 设备,另一个面向 x64 模拟器。 它们有单独的平台专用源集,但实际上,设备和模拟器很少需要不同的代码,它们的依赖项很相似。 因此,iOS 专用代码可以在它们之间共享。
很显然,在此设置中,两个 iOS 目标有共享的源集十分可取,Kotlin/Native 代码仍然可以直接调用 iOS 设备和模拟器通用的任何 API。
现在,您可以借助分层项目结构支持实现此目标,该支持将根据目标使用 API 和语言功能的源集对其中的 API 和功能进行推断和调整。
使用方法
将以下标志添加到项目的 gradle.properties
文件中:
请注意,从 Kotlin 1.4-M2 开始,分层结构以及所有多平台项目都需要 Gradle 6.0 或更高版本。
您可以使用目标快捷键(可用于典型多目标场景)创建分层结构,或通过连接源集手动创建。
例如,使用 ios()
快捷键创建上面所示的两个 iOS 目标和共享源集:
对于其他目标组合,可以通过连接具有 dependsOn
关系的源集手动创建层次结构。
您可为以下目标组合创建共享源集:
- JVM + JS + Native
- JVM + Native
- JS + Native
- JVM + JS
- Native
目前,我们不支持为以下组合共享源集:
- Several JVM targets
- JVM + Android targets
- Several JS targets
请发送电子邮件至 feedback@kotlinlang.org 联系我们,共享您的目标组合。 这将帮助我们优先考虑更常用的组合。
在库中共享代码
借助分层项目结构,库也可为目标子集提供通用 API。
发布库时,其共享源集的 API 会与项目结构信息一同嵌入到库工件中。 使用此库时,项目的共享源集会准确访问每个源集的目标可以使用的库 API。
例如,查看kotlinx.coroutines 存储库 native-mt 分支中的以下源集层次结构:
并发源集声明函数 runBlocking
并针对 JVM 和原生目标进行编译。 您可以依赖此函数并从 JVM 目标和原生目标之间共享的源集调用 runBlocking()
,因为这样会匹配库 concurrent
源集的“目标签名”。
只指定一次依懒项
从现在开始,您应当仅在共享源集中指定一次依赖项,而不是在使用某个库的共享和平台专用源集中该库的不同变体上指定依赖项。
不要使用带有指定平台的后缀的 kotlinx 库工件名称,例如 -common
、-native
或类似名称,因为它们不再受支持。请改用库基础工件名称,在上述示例中为 kotlinx-coroutines-core
。 不过,这一变化目前不会影响 stdlib
和 kotlin.test
库(stdlib-common
和 test-common
);我们会稍后对它们进行处理。
如果您只需要为特定平台使用依赖项,仍可以使用标准和 kotlinx 库的平台专用变体(带有 -jvm
或 -js
等后缀),例如kotlinx-coroutines-core-jvm
。
在分层结构中使用原生库
您可以在多个原生目标之间共享的源集中使用依赖于平台的库,例如 Foundation
、UIKit
和 posix
。 这样可以帮助您共享更多的原生代码,而不受平台专用依赖项限制。
无需其他步骤——一切都可以自动执行。 IntelliJ IDEA 会帮助您检测可以在共享代码中使用的通用声明。
不过请注意,有一些限制:
- 此方法仅适用于在平台专用源集之间共享的原生源集。 不适用于在更高级别的源集层次结构中共享的原生源集。 例如,如果您拥有
nativeDarwinMain
(watchosMain
和iosMain
的父级),其中iosMain
有iosArm64Main
和iosX64Main
两个子级,您可以将依赖于平台的库仅用于iosMain
,而不用于nativeDarwinMain
。 - 此方法仅适用于 Kotlin/Native 随附的互操作库。
详细了解 技术详细信息。
使用方法
要在共享源集中使用依赖于平台的库,请将以下代码添加到您的 gradle.properties
中:
分享分层结构的反馈
请注意,分层项目结构当前为技术预览版,仍在开发中。 您可以查看我们要解决的已知问题,其中一些已有解决方案。
请随时在 Kotlin Slack 的 #multiplatform 频道 中寻求帮助,并向我们的问题跟踪器 YouTrack 报告错误。 这是一个复杂且重要的功能,因此您的反馈将十分有用!
多平台项目中需要 Gradle 6.0 或更高版本
从 Kotlin 1.4-M2 开始,所有多平台项目都需要 Gradle 6.0 或更高版本。 请确保为使用 kotlin-multiplatform
插件的项目升级 Gradle。
灵活的新项目向导
使用灵活的新 Kotlin 项目向导,您可以在一个位置轻松创建和配置不同类型的 Kotlin 项目,包括多平台项目,在这些项目中,没有 UI 很难进行配置。
之前,您可以从提供不同配置选项的不同位置创建 Kotlin 项目。 现在,可以在一个位置执行操作,提高了简便性和灵活性:
- 根据您要执行的操作,选择项目模板/strong>。
- 选择构建系统 — Gradle(Kotlin 或 Groovy DSL)、Maven 或 IntelliJ。 此向导仅会显示选定项目模板支持的构建系统。
- 直接在主屏幕上预览项目结构
然后,您可以完成项目创建,或者在下一个屏幕上配置项目:
- 添加/移除此项目模板支持的模块和目标
- 配置模块和目标设置,例如,目标 JVM 版本、目标模板和测试框架。
- 在以下模块之间设置模块依赖关系:
- iOS 与多平台模块
- Android 与多平台模块
- JVM 模块
未来,我们会通过添加更多配置选项和模板来使 Kotlin 项目向导更灵活。
使用方法
- 安装 1.4-M2 Kotlin 插件
- 在 IntelliJ IDEA 中,点击 File | New | Project
- 在左侧面板中,选择 Kotlin (Experimental Wizard)
- 创建您的新 Kotlin 项目/li>
利用显式 API 模式实现一致和描述良好的 API
我们将引入一个新的编译器模式来帮助库作者创建一致且描述良好的 API。 在这个显式 API 模式中,编译器会对向库公共 API 公开的声明执行其他检查:
- 如果默认可见性会向公共 API 公开声明,声明将需要可见性修饰符。 这将有助于确保没有声明会被无意公开。
- 向公共 API 公开的属性和函数需要显式类型规范。 这会确保 API 用户可以了解他们使用的 API 成员的类型。
根据您的配置,这些检查可以产生错误(strict 模式)或警告(warning 模式)。
我们计划未来添加更多检查,以提升您的库创作体验。 您可以在此 KEEP 中了解详情。 不过,您已经可以试用显式 API 模式并和我们分享您的反馈。
要在显式 API 模式中编译您的模块,请向您的 Gradle 构建脚本中添加以下其中一行:
在 Groovy 中,您可以使用替代语法:
使用命令行编译器时,请将 -Xexplicit-api
编译器选项设置为 strict
或 warning
:
Kotlin/Native 对挂起函数的支持和其他改进
在此预览版中,我们终于在 Swift 和 Objective-C 中添加了对 Kotlin 的挂起函数的支持,目前仅涵盖基本情况。 我们一直致力于让您能够在 Swift 和 Objective-C 应用程序中充分利用协同程序。 除此之外,我们还准备展示我们在 Kotlin/Native 的性能和稳定性方面取得的一些成果。
在 Swift 和 Objective-C 中支持 Kotlin 的挂起函数
我们会继续扩展对在 Swift 和 Objective-C 代码中使用主要 Kotlin 功能的支持。 之前版本中的一个已知缺点是不完全支持 Kotlin 协同程序:Swift 或 Objective-C 代码中不支持挂起函数。
在 M2 预览版中,我们非常高兴在 Swift 和 Objective-C 中提供对挂起函数的基本支持。 现在,当您将 Kotlin 模块编译到 Apple 框架中时,挂起函数可在其中用作包含回调(Swift/Objective-C 术语中的 completionHandler
)的函数。 当生成框架标头中具有此类函数时,您可以从 Swift 或 Objective-C 代码中调用,甚至重写它们。
例如,如果您编写此 Kotlin 函数:
…然后,您可以这样从 Swift 调用它:
请注意,在 M2 预览版中,您只能从主线程调用挂起函数。
使用间距图标运行 Kotlin/Native 代码
之前,您只能在终端中或通过在 IntelliJ IDEA 中运行 Gradle 任务的方式运行 Kotlin/Native 代码。 现在,您可以使用间距图标轻松运行它,与运行其他 Kotlin 代码相似。
C 互操作的性能改进
在改进 Kotlin/Native 的性能方面,我们重新设计了 C 互操作库的构建方式。(这些库是一些工件,让您能够在 Kotlin 代码中使用 C 和 Objective-C 库的声明。) 这些变更在后台完成,但可见的是提升的性能和更小的工件:新工具使生成互操作库的速度比之前快 4 倍,工件大小仅为之前的 25% 至 30%!
现在,使用互操作库的速度也更快,因为在 Kotlin 1.4-M2 中使用 C 互操作编译 Kotlin 项目需要的时间更少。
编译器缓存和 Gradle 守护程序使用趋于稳定
在 1.3.70 中,我们引入了两个新功能来改进 Kotlin/Native 编译的性能:缓存项目依赖项和从 Gradle 守护程序运行编译器。 还有一些工作仍在进行,所以您可能会遇到问题,并在一些情况下缺乏稳定性。
感谢大家的反馈,我们设法解决了多个问题并提升了这些功能的整体稳定性。 因此,如果您之前遇到过问题,或者您还没有试用最新版本的 Kotlin/Native,现在正是一个好机会。
Kotlin/JS 改进
在 1.4-M2 中,Kotlin 的 JavaScript 目标会更紧密地将其 Gradle 命名惯例与其他 Kotlin 目标的命名惯例保持一致。 它还添加了对编译器设置的更精细控制,使 @JsExport
注解通用化,并在默认情况下通过 webpack 实现了 CSS 支持。
Gradle DSL 变更
命名变更
为了与其他 Kotlin 目标更紧密地保持一致,我们更改了 Kotlin/JS Gradle 配置一些常用部分的名称。 以 1.4-M2 中 Kotlin/JS Gradle 项目的这个默认配置块为例,它说明了我们所做的两个命名变更:
target
变为js
,与用于 Kotlin 多平台插件的语法保持一致。- 在 Kotlin 1.4-M1 中引入的
produceExecutable()
变为binaries.executable()
,与用于 Kotlin/Native 的命名保持一致。
如果您想要详细了解 binaries.executable()
的作用,请参阅 1.4-M1 博文 中的“Kotlin/JS | Gradle DSL 变更”部分。
按项目的编译器设置
在 Kotlin 1.4-M1 中,我们首次引入了带优化的 DCE、TypeScript 声明预览等的新 IR 编译器后端,包括 gradle.properties
中用于在默认、IR 和两种编译器模式之间切换的设置。在 M2 中,可以按项目直接从 Gradle 配置对使用的编译器模式进行更精细的控制。
要在不同编译器模式之间切换,请将编译器类型传递到 Gradle 构建脚本中的 js
函数。 例如:
这样为项目设置编译器类型会重写 gradle.properties
中指定的默认设置。
支持从 Gradle 访问 webpack 的 css-loader
由于 Kotlin/JS Gradle 插件默认使用 webpack 为浏览器创建工件,可以自定义许多设置。 尽管可以通过直接修改用于构建项目的 webpack 配置文件 更改所有选项,我们仍想直接通过 Gradle DSL 提供对最常用设置的访问。
默认情况下,Kotlin 1.4-M2 会为将浏览器作为目标的项目启用 webpack 的 css-loader
。 这意味着,将 CSS 添加到您的项目以及包含样式表的依赖项现在大多数情况下开箱即用,无需任何其他配置。 之前,在这种情况下,您可能会遇到 Module parse failed: Unexpected character '@' (14:0)
一类的错误。
如果您想调整此 CSS 集成的行为,可以通过使用 js.browser.webpackTask.cssSettings
执行这一操作。
使用 cssSettings.enabled
,您可以更改项目是否应使用 css-loader
(默认情况下已启用)。
使用 cssSettings.mode
,您可以指定如何处理遇到的任何 CSS。 可以使用下列值:
"inline"
(默认):样式已添加到全局<style>
标记中。"extract"
:样式已提取到单独的文件中。 然后,HTML 页面就可以包含它们。"import"
:样式作为字符串处理。 如果您需要从代码访问 CSS,这将十分有用(如val styles = require("main.css")
)。
如果您想要为同一项目使用不同模式,可以使用 cssSettings.rules
。 您可以指定 KotlinWebpackCssRules
列表,每个规则定义一种模式以及 include 和 exclude 模式。 如果您想要详细了解这些模式,请参阅 include 和 exclude 规则的 webpack 文档。
可自定义的模块名称
您现在可以直接从 Gradle 构建脚本更改 JavaScript 模块名称:
这将更改 build/js/packages/myModuleName
中生成的模块名称,包括相应的 .js
和 .d.ts
文件名。请注意,这不会影响 build/distributions
中的 webpack 输出。要更改 webpack 文件的名称,您可以使用 js.browser.webpackTask.outputFileName
。
通用代码 @JsExport
注解
现在,通用代码中支持 @JsExport
注解,您可以在使用 IR 编译器后端时通过它在 JavaScript 或 TypeScript 中使用顶级声明。 这样就无需引入自定义注解和类型别名,有助于从多平台 Kotlin 项目方便地构建 JavaScript 库。
其他质量改进和值得注意的修复
- 用于浏览器和 nodejs 目标的典型操作的 Gradle 任务现在分成单独的任务组。
kotlin browser
和kotlin code
组会显示在 IntelliJ IDEA 的 Gradle 工具窗口中或在通过./gradlew tasks --all
列出任务时出现。 - 为 node.js 目标运行测试时,调试器现在可以在断点处正确停止。
- 对于使用
both
模式进行编译的项目和库,现在能够正确地解析 klib 依赖关系。
兼容性
请注意,在一些极端情况下,Kotlin 1.4 不会向后兼容 1.3。 所有这些情况都已接受语言委员会的仔细检查,将列在“兼容性指南”(类似于 此指南))中。 当前,您可以在 YouTrack 中找到此列表。
预发布说明
请注意,后向兼容性保证不涵盖预发布版本。 功能和 API 在后续版本中可能发生变化。 在我们发布最终 RC 时,预发布版本产生的所有二进制文件都会被编译器禁止,您需要重新编译通过 1.4‑Mx 编译的所有内容。
如何试用最新功能
和往常一样,您可以在 play.kotl.in 上 在线试用 Kotlin。
在 IntelliJ IDEA 和 Android Studio 中,您可以将 Kotlin 插件更新为 1.4-M2。 查看 如何执行此操作。
如果您想处理在安装该预览版之前创建的现有项目,则需要 在 Gradle 或 Maven 中针对预览版配置您的构建。
您可以从 Github 版本页面 下载命令行编译器。
您可以使用随此版本一起发布的以下库:
- kotlinx.atomicfu 版本:0.14.3-1.4-M2
- kotlinx.coroutines 版本:1.3.7-1.4-M2
- kotlinx.serialization 版本:0.20.0-1.4-M2
- ktor 版本:1.3.2-1.4-M2
您也可以在 此处 找到版本详细信息和兼容库的列表。
分享您的反馈
如果您发现错误并在 YouTrack问题跟踪器中报告,我们将不胜感激。 我们将尽力在最终版本之前修复所有重要问题,也就是说,您不用等到下一个 Kotlin 版本即可看到问题得到解决。
也欢迎您加入 Kotlin Slack 上的 #eap 频道(在 此处获取邀请)。在此频道中,您可以提问、参与讨论,以及获取新预览版本的通知。
Let’s Kotlin!
外部贡献者
我们要感谢所有的外部贡献者,此版本中包含了他们的拉取请求:
- Toshiaki Kameyama
- Victor Turansky
- Jinseong Jeon
- Steven Schäfer
- Juan Chen
- Mark Punzalan
- Kristoffer Andersen
- Mads Ager
- Nick
- Polina Koval
- Konstantin Virolainen
- n-p-s
- Jiaxiang Chen
- Matthew Gharrity
- Martynas Sateika
- Nadezhda Petelimova
- Philippe Ombredanne
- Pierre-Luc Carmel Biron
- Kevin Bierhoff
- Scott Weber
- Miguel Serra
- Ivan Gavrilovic
- Irene Dea
- Harry
- Stanislav Ruban
- Brian Plummer
- Adam McNeilly