时光飞逝,今天我们想向你展示Kotlin 1.4的部分强大的预览特性。在Kotlin 1.4正式发布之前,请了解并尝试Kotlin 1.4-M2。

我们很感谢试用了Kotlin 1.4首个预览版并反馈以帮助Kotlin变得更完善的人!
也非常感谢尝试了在上一篇博文所提到的*Kotlin 1.4-M2’s标准库的改动的人。
在这篇博文中,我们将重点介绍1.4-M2中可用的新特性和关键改进:
- 得益于多平台项目的分层架构,现在支持在多个目标中共享代码。
- 一个新的更灵活的Kotlin项目创建向导,更便于创建和配置不同类型的项目。
- 一个新的有助于库作者的编译器模式,其名称为API模式,有助于创建统一且描述清晰的API。
- 支持在Kotlin/Native调用Swift和Objective-C的挂起函数。
- 完善了Kotlin/JS的Gradle DSL,支持CSS开箱即用及常见的注解导出。
你可以在更新日志中找到完整的变更列表。我们同样非常感谢其他贡献者。
多目标分层项目架构中共享代码
随着项目分层架构的支持,你可以在多平台项目的多个目标中共享代码。
在此之前,多平台项目中的代码要么被放入到平台的指定源集中(仅限于一个目标,并且不能被任何其他平台复用),要么放入到公共源集中,例如commonMain
或commonTest
,在项目中的所有平台之间共享。在公共源集中,你只能调用被expect
声明的平台独立实现的actual
API。
虽然这让在所有目标之间共享代码变得容易,但是在目标之间的共享却并不容易,尤其复用通用逻辑和第三方API的相似目标。
例如,在针对iOS的典型多平台项目中,有两个与iOS相关的目标:一个针对iOS ARM64设备,另一个针对x64模拟器。它们具有独立的平台指定的源集,但是在实践中,几乎不需要为设备和模拟器使用不同的代码,并且它们的依赖非常相似。因此可以在它们之间共享iOS平台特定的代码。
显然,在此设置中,希望能有两个iOS目标的共享源集,并且Kotlin/Native代码仍可以直接调用iOS设备和模拟器共通的任何API。

现在你可以在分层项目架构来实现这一点,它会根据调用方的目标来推断和调整每个源集中可用的API和语言功能。
如何使用
Install the 1.4 M2 Kotlin plugin with the hierarchical project support right now!
在你的项目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和Native目标进行编译。你可以在面向JVM及Native的目标中依赖并调用runBlocking()
,您可以依赖它,并从JVM目标和本机目标之间共享的源集中调用runBlocking(),因为它会匹配库的concurrent
源集中的“目标签名”。
只需要指定一次依赖
从现在开始,不需要在共享和平台相关的源集中对同一库指定不同变体的依赖,而应该在共享源集中仅指定一次依赖关系。
不要使用有特定平台后缀的kotlinx库工件名称,例如-common
,-**native**
或类似名称,因为它们已不再受支持。请使用库的基本工件名称取而代之,在上面的示例中,其名称为kotlinx-coroutines-core
。但是这个更改目前不影响stdlib
和kotlin.test
库(stdlib-common
和test-common
);它们被安排在之后。
如果只需要特定平台的依赖,则仍然可以使用标准库和kotlinx库的平台特定变体,后缀为-jvm
或-js
,例如kotlinx-coroutines-core-jvm
。
在分层结构中使用native库
你可以在多个native目标之间共享的源集中使用平台相关的库,例如Foundation
,UIKit
或posix
。这可以帮助你共享更多的native代码,而不受平台特定的依赖限制。
无需任何步骤,这一切都会自动完成。 IntelliJ IDEA将帮助你检测可在共享代码中使用的通用声明。
但是请注意,存在一些限制:
- 该方法仅适用于共享给平台特定源集之间的native源集。而不适用于共享给更高层级源集的native源集。
- 例如,如果你有一个
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项目。现在只有一个地方可以做到这一点,它保证了简洁而又不失灵活:
- 选择项目模板,具体取决于你要执行的操作。
- 选择构建系统——Gradle(Kotlin或Groovy DSL),Maven或IntelliJ。该向导仅显示所选项目模板支持的构建系统。
- 在主界面上预览项目结构。
然后,你可以完成创建项目,或者(可选)在下一个界面上配置项目:
- 添加/删除项目模板所支持的模块和目标。
- 配置模块和目标设置,例如目标JVM版本,目标模板和测试框架。

- 设置模板间的依赖关系:
- iOS和多平台模块
- Android和多平台模块
- JVM模块

未来我们将通过添加更多配置选项和模板来使Kotlin项目向导更为灵活。
如何使用
- 安装1.4-M2 Kotlin插件。
- 在IntelliJ IDEA中点击File | New | Project。
- 在左侧的面板中选择Kotlin (Experimental Wizard)。
- 创建你的新Kotlin项目。
显式API模式:统一且描述清晰的API
我们正在引入一种新的编译器模式,以帮助库作者创建一致且描述良好的API。在这种显式的API模式下,编译器会对库的公共API声明进行额外的检查:
- 如果是默认可见性公开的公共API,则(API)声明必须包含可见性修饰符。这有助于确保不会在无意间公开为public。
- 对于public API公开的属性和函数,需要明确其类型。这样可以确保API的用户知道他们要用到的API成员类型。

根据你的配置,检查后会发出错误(strict 模式)或警告(warning模式)。
我们计划将来增加更多检查,以改善你编写代码库的体验。你可以在KEEP中了解有关的更多信息。但是你已经可以尝试显式API模式并与我们分享你的反馈。
要在显式API模式下编译模块,请在Gradle构建脚本中添加以下配置:
kotlin { explicitApi() // for strict mode // or explicitApiWarning() // for warning mode }在Groovy中,你可以使用这样的语法:
当使用命令行编译器时,请在-Xexplicit-api
编译器选项中使用strict
或warning
:
Kotlin/Native支持挂起函数及其他改进
在该预览中,Kotlin终于支持Swift和Objective-C中的挂起函数了,目前仅涵盖了基本场景。我们一直在努力为Swift和Objective-C应用程序提供协程的完整功能。除此之外,我们准备介绍Kotlin/Native的性能及稳定性方面的一些工作成果。
Kotlin支持Swift和Objective-C的挂起函数
我们将继续扩展Swift和Objective-C代码中对Kotlin关键功能的支持。之前版本已知的其中一个缺点是它们不完全支持Kotlin协程:没有为Swift或Objective-C代码提供挂起函数。
在M2预览中,我们很高兴为Swift和Objective-C中的挂起函数提供了基本支持。现在,当你将Kotlin模块编译成Apple框架时,其中的挂起函数可以作为带有回调的函数使用(Swift/Objective-C术语中的completionHandler
)。如果在生成的框架头文件中具有此类函数,则你可以在Swift或Objective-C代码中调用它们,甚至重写它们。
例如,当你编写这样一个Kotlin函数:
…然后你可以在Swift上如此调用:
请注意在M2预览中,你只能在主线程中调用挂起函数。
通过gutter图标运行Kotlin/Native代码
之前你只能在Terminal中运行Kotlin/Native代码,也可以在IntelliJ IDEA中通过Gradle任务运行。而现在,你可以方便地使用gutter图标去运行,就像其他Kotlin代码一样。

C互操作性的性能改进
在提高Kotlin/Native性能的范围内,我们重新设计了C互操作库的构建方式。 (这些库是允许你在Kotlin代码中使用C和Objective-C库声明的工件。)这些变化虽然是肉眼不可见的,但可以感受到性能的提高和工件体积的减小:新工具的生成速度是以前的4倍,工件的大小是以前的25%到30%!
使用interop库现在也更快,因为在Kotlin 1.4-M2用C interop编译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,我们首先引入的新IR编译器后端,具有DCE优化,TypeScript声明预览等功能,其中包含一个在gradle.properties
中的设置,可在默认,IR和同时启用的编译器模式之间切换。 M2直接从Gradle配置中引入了对每个项目所使用的编译器模式更细粒度的控制。
要在不同的编译器模式之间切换,请将编译器类型传递给Gradle构建脚本的js
函数。例如:
像这样为项目设置的编译器类型会覆盖gradle.properties
中指定的默认设置。
Gradle支持Webpack的CSS加载器
由于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
列表,每个列表定义一个模式以及包含和排除的规则。如果你想了解更多有关这些模式的信息,请查阅webpack文档中的包含和排除规则。
自定义模块名
现在,你可以直接在Gradle构建脚本中改变JavaScript的模块名称:
这将影响到在build/js/packages/myModuleName
中生成的模块名称,包括相关的.js
和.d.ts
文件名。请注意,这不会影响Webpack在build/distributions
中的输出。要更改webpacked文件的名称,可以使用js.browser.webpackTask.outputFileName
。
通用代码的@JsExport
注解
@JsExport
注解现可在通用代码中使用,该注解在IR编译器后端启用时从JavaScript或TypeScript中生成顶级声明。这避免了引入自定义注解和类型别名,并铺平了多平台Kotlin项目更便捷构建JavaScript库的道路。
其他体验改进及重要修复
- 用于浏览器和nodejs目标的常规Gradle任务现被划分到单独的任务组中。当通过
./gradlew tasks --all
列出所有任务时,kotlin browser
和kotlin node
组将被显示到IntelliJ IDEA的Gradle工具窗口中。 - 现在,在为node.js目标运行测试时,调试器可以正确地在断点处停止了。
- 对于
同时使用两种编译模式
的项目和库,现在能正确处理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
在这里查看有关发行版的更多细节和兼容库列表。
分享你的反馈
如果你发现错误并向我们的问题跟踪器进行报告,我们表示非常感谢。我们尝试在最终发行版前解决所有重要问题,这意味着无需等到下一个Kotlin发行版你的问题便能得到解决。
如果你有任何疑问并想参与讨论,欢迎加入Kotlin Slack (在这里获得邀请)的#eap频道。在该频道中,你还可以获取有关新预览版的通知。
Let’s Kotlin!
其他贡献者
同样感谢提交的PR合并到该版本中的所有其他贡献者:
- 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
Pingback引用通告: Kotlin 1.4-M3带着新的标准库来了! - KotlinCn
Pingback引用通告: Kotlin 1.4.0-RC! - KotlinCn