Dart2.18

将 Dart 引入 Objective-C 和 Swift 互操作

我们在 2020 年预览了用于调用本机 C API 的 Dart 外部函数接口 (FFI),并于 2021 年 3 月在 Dart 2.12 中发布了该接口。自该版本以来,大量包已利用此功能与现有的本机 C API 集成。一些示例包括 、、、、 和 。file_picker``printing``win32``objectbox``realm``isar``tflite_flutter``dbus

Dart 团队希望 Dart 支持与运行 Dart 的平台上所有主要语言的互操作性。Dart 2.18 达到了实现这一目标的下一个里程碑。您的 Dart 代码可以调用 Objective-C 和 Swift 代码,通常用于 macOS 和 iOS 平台上的 API。Dart 在任何应用程序中都支持这种互操作机制,从 CLI 应用程序到后端代码再到 Flutter UI。

这种新机制利用了Objective-C和Swift代码可以基于API绑定作为C代码公开的事实。Dart API 包装器生成工具 可以从 API 标头创建这些绑定。让我们看一个例子。ffigen

使用 Objective-C 的时区示例

macOS 有一个 API,用于查询上公开的时区信息。您可以查询此 API 以获取用户为其设备配置的时区和 [UTC 时区偏移量](https://www.w3.org/International/core/2005/09/timezone.html#:~:text=What is a "zone offset,or "-" from UTC.)。NSTimeZone

以下示例 Objective-C 应用程序使用此时区 API 来获取系统时区和 GMT 偏移量:

该应用程序导入 ,其中包含 Apple 基金会库的 API 标头。接下来,在方法内部,它从类调用该方法。此方法返回设备上具有所选时区的实例。最后,应用将两行输出到控制台,其中包含时区名称和 UTC 偏移量(以小时为单位)。Foundation.h``main``systemTimeZone``NSTimeZone``NSTimeZone

如果运行此应用,它应返回类似于以下内容的内容,具体取决于你的位置:

Timezone name: Europe/Copenhagen
Timezone offset GMT: 2 hours

使用飞镖的时区示例

让我们使用新的 Objective-C 互操作在 Dart 中复制这个结果。

首先创建一个新的 Dart CLI 应用:

$ dart create timezones

然后编辑文件以包含配置。此配置指向头文件,并列出哪些 Objective-C 接口应生成包装器:pubspec``ffigen

这将为标头选择Objective-C绑定,并仅包含接口中的API。要生成包装器,请运行:NSTimeZone.h``NSTimeZone``ffigen

$ dart run ffigen

此命令创建一个新文件 ,其中包含一堆生成的 API 绑定。使用此绑定文件,我们可以编写 Dart 方法。此方法镜像了 Objective-C 代码:foundation_bindings.dart``main

就是这样!这种新的支持从今天的 Dart 2.18 开始处于实验状态。这增强了Dart的通用互操作支持,可以直接调用macOS和iOS API。这反过来又补充了 Flutter 的插件,提供了适用于任何 Dart 应用程序的新支持,并允许您直接从 Dart 代码调用 macOS 和 iOS API。

我们欢迎您的反馈。通过在 GitHub 上的反馈问题中发表评论,让我们知道哪些有效、哪些可以更改或您遇到了什么问题。要了解有关此互操作性的更多信息,请参阅 Objective-C 和 Swift 互操作性指南

特定于平台的 http 库

Dart包括一个通用的多平台库。此库允许您编写代码,而无需考虑平台细节。有时,您可能希望编写特定于特定主机平台的网络 API 的代码。http

例如,Apple的网络库允许指定仅限WiFi的网络或需要VPN。为了支持这些用例,我们创建了一个适用于 macOS 和 iOS 平台的新网络包。这建立在上一节中提到的新的Objective-C互操作之上。它使用从 Foundation 中的 Apple 网络 API 生成的大量 API 包装器。NSURLSession``cupertino_http

库比蒂诺 http 库示例

以下示例将 Flutter 应用程序的 http 客户端设置为使用 macOS 和 iOS 上的库,以及 Dart 在其他平台上的常规 http 库:cupertino_http``dart:io

完成此初始配置后,应用将在特定客户端上进行任何后续网络调用。例如,http 请求现在类似于以下内容:get()

当您无法使用通用客户端接口时,可以使用库直接调用 Apple 的网络 API:cupertino_http

多平台应用中特定于平台的网络

当我们设计此功能时,目标仍然是使应用尽可能多平台。为了实现这一目标,我们保留了用于基本 http 操作的通用多平台 API,并允许配置每个平台要使用的网络库。可以使用客户端 API 最大程度地减少需要编写的平台特定代码量。此 API 可以按平台配置,但以独立于平台的方式使用。http``package:http

Dart 2.18 提供了对两个支持客户端 API 的平台特定 http 库的实验性支持:package:http

  • cupertino_http基于 macOS/iOS。NSURLSession
  • cronet_http基于Cronet,在Android上流行的网络库。

将通用客户端 API 与多个 HTTP 实现相结合,可以两全其美。您可以获得特定于平台的行为,同时仍从所有平台的一组共享源维护您的应用。我们很想听听你对这个 GitHub 问题的反馈。

改进的类型推断

Dart 使用许多泛型函数。请考虑该方法,该方法将元素集合减少为单个值。下面的示例计算整数列表的总和:fold

List<int> numbers = [1, 2, 3];
final sum = numbers.fold(0, (x, y) => x + y);
print(‘The sum of $numbers is $sum’);

对于 Dart 2.17 或更早版本,此方法返回类型错误:

line 2 • The operator ‘+’ can’t be unconditionally invoked because the receiver can be ‘null’.

Dart的类型推断无法在参数之间流动信息。这导致了 类型的不确定性。要纠正潜在的错误,您需要指定类型:x

final sum = numbers.fold(0, (int x, int y) => x + y);

Dart 2.18 改进了类型推断。前面的示例通过静态分析,可以推断 x 和 y 都是不可为空的整数。此更改允许您编写更简洁的 Dart 代码,同时保留强推断类型的完整健全性属性。

异步性能改进

此版本的 Dart 改进了 Dart VM 应用方法和 / 生成器函数的方式。这将减少代码大小。在两个大型内部 Google 应用中,我们看到 AOT 快照大小减少了约 10%。我们还看到了微基准测试的性能提升。async``async*``sync*

这些更改包括其他小的行为更改;要了解更多信息,请参阅更新日志

pub.dev 改进

结合 2.18 版本,我们对包存储库进行了两项更改。pub.dev

个人经常在业余时间维护发布的包。这可能在时间和财务方面都很昂贵。为了便于赞助,我们现在支持 中的新标记,包发布者可以使用该标记列出指向一种或多种包赞助方式的链接。然后,这些链接将显示在侧边栏中:pub.dev``funding``pubspec``pub.dev

img

要了解更多信息,请参阅文档pubspec

此外,我们希望鼓励开源包的丰富生态系统。为了强调这一点,自动包评分对使用 OSI 批准的许可证的包额外奖励 10 分。pub.dev

一些重大更改

Dart非常注重简单性和可学习性。在添加新功能时,我们一直在努力保持谨慎的平衡。保持简单的一种方法是删除历史功能和 API,很少使用或更好的替换。Dart 2.18 清理了此类别中的项目,包括一些较小的中断性更改:

  • 早在 2020 年 10 月,我们就添加了统一的 CLI 开发人员工具。在 2.18 中,我们完成了转换。此版本删除了最后两个已弃用的工具(使用 ) 和 (使用 )。dart``dart2js``dart compile js``dartanalyzer``dart analyze
  • 随着语言版本控制的引入, 会生成一个新的解析文件:以前的文件 , 使用不能包含版本的格式。我们停止使用该文件。如果您有任何文件,可以将其删除。pub``.dart_tool/package_config.json.``.packages``.packages``.packages
  • 不能使用不扩展的类的混合(中断性变更 #48167)。此行为从来都不是有意为之。Object
  • ‘s 的属性已更改为可为空(重大更改 #49045)。uri``dart:io``RedirectException
  • 已删除遵循SCREAMING_SNAKE约定的 网络 API 中的常量(中断性变更 #34218;以前已弃用)。请改用相应的小驼峰大小写常量。dart:io
  • Dart VM 在退出时不再恢复初始终端设置。更改设置的程序,现在负责在程序退出时恢复设置(中断性变更 #45630)。Stdin``lineMode``echoMode

空安全更新

我们很高兴看到自 2020 年 11 月测试版和 2021 年 3 月发布 Dart 2.12 以来,空安全得到了广泛使用。

首先,大多数流行软件包的应用程序开发人员都迁移到了空安全。分析表明,前 250 个包中的 100% 和最常用的前 1,000 个包中的 98% 支持空安全。pub.dev

其次,大多数应用开发人员在具有完全空安全迁移的代码库中工作。这一点至关重要。Dart 的完整声音零安全在迁移所有代码和所有依赖项(包括可传递)之前不会启动。我们通过命令中的遥测对此进行跟踪。flutter run

下图显示了 的无声与无声安全执行。在引入零安全之前,两者都没有。随之而来的是不健全的零安全迅速增长。随着应用程序开始迁移到空安全,开发人员进行了部分迁移。有些部分仍需要迁移。随着时间的推移,我们看到声音零安全会话非常健康地增长。到上月底,声音零安全会议比不健全的会议多四倍。我们希望,在接下来的几个季度里,我们将看到声音零安全接近100%!flutter run

img

重要的空安全路线图更新

同时支持无声和无声零安全会增加开销和复杂性。

首先,Dart开发人员需要学习和理解这两种模式。每当读取一段 Dart 代码时,请检查语言版本以查看类型是默认为非 null(Dart 2.12 及更高版本)还是默认为空(Dart 2.11 及更早版本)。

其次,在我们的编译器和运行时中同时支持这两种模式会减慢 Dart SDK 的发展速度,以支持新功能。

基于不健全零安全的开销以及上一节中提到的非常积极的采用数字,我们的目标是过渡到仅支持声音零安全,并停止非零安全和不健全的零安全模式。我们暂定于 2023 年年中发布。\

这意味着停止对 Dart 2.11 及更早版本的支持。具有 SDK 约束下限小于 2.12 的 Pubspec 文件在 Dart 3 及更高版本中将不再解析。在包含语言标记的源代码中,如果设置为小于 2.12(例如),这些标记将失败。// @dart=2.9

如果已迁移到声音空安全,则代码将在 Dart 3 中使用完全空安全。如果您还没有,请立即迁移!若要了解有关这些更改的详细信息,请参阅此 GitHub 问题

总结

对互操作、网络、类型推断的新支持现已推出。要开始使用,您可以直接下载 Dart 2.18 版本,或将其作为今天 Flutter 3.3 SDK 版本的一部分嵌入。pub.dev

Dart 2.17: 生产力和集成

语言功能。生产力工具。更深入、更广泛的平台集成。

今天在Google I/O上,我们宣布了一个新的Dart SDK,版本2.17。此版本基于我们领先的生产力和平台可移植性的核心主题。它提供了新的语言功能:具有成员支持的枚举,改进了向超类的参数转发,以及命名参数的更大灵活性。我们改进了工具,增加了一个新的主要版本(我们的工具支持,用于根据最佳实践检查 Dart 代码),并广泛更新了包含丰富代码示例的核心库 API 文档。为了改进平台集成,我们提供了在 Flutter 插件中使用(本机 C 互操作)的新模板,对 RISC-V 处理器的实验性支持,以及对 macOS 和 Windows 可执行文件签名的支持。package:lints``dart:ffi

飞镖 2.17 轻松横幅

提高工作效率的新语言功能

我们不断改进 Dart 语言,通过添加新功能和改进现有功能来提高您的工作效率。Dart 2.17 为枚举上的成员添加了重要的新支持,改进了在构造函数中使用命名参数的方式,并使将参数转发到超类的代码变得不那么冗长和重复。

具有成员的增强枚举

枚举非常适合表示一组离散的状态。例如,我们可以将水建模为 .但是,如果我们想在 上添加一些方法,例如,将每个状态转换为温度,并支持将 转换为 ?我们也许可以使用扩展方法来添加一个方法,但我们必须小心地使其与 .对于转换,我们更愿意覆盖,但这一直不受支持。enum Water { frozen, lukewarm, boiling }``enum``enum``String``waterToTemp()``enum``String``toString()

在 Dart 2.17 中,我们现在对枚举上的成员提供了一般支持。这意味着我们可以添加保存状态的字段、设置该状态的构造函数、具有功能的方法,甚至覆盖现有成员。你们中的许多人一直在请求此功能;这是我们在语言追踪器中投票第三高的问题

对于我们的水示例,我们可以添加一个保存温度的字段和一个默认构造函数,该构造函数采用:int``int

enum Water {
…
  final int tempInFahrenheit;
  const Water(this.tempInFahrenheit);
}

为了确保在创建 时调用构造函数,我们需要为每个值调用它:enum``enum

enum Water {
  frozen(32),
  lukewarm(100),
  boiling(212);
…
}

为了支持转换为 ,我们只需覆盖 ,它继承自:String``toString``enums``Object

@override
String toString() => "The $name water is $tempInFahrenheit F.";

有了它,你就有一个可以轻松实例化的完整,你可以在以下位置调用方法:enum

void main() {
  print(Water.frozen); // Prints “The frozen water is 32 F.”
}

下面说明了这两种方法的完整示例;我们发现新的Dart 2.17版本更容易阅读和维护。

img

超级初始值设定项

当您具有类继承层次结构时,常见的模式是将一些构造函数参数传递给超类的构造函数。为此,子类需要 1) 在其自己的构造函数中列出每个参数,以及 2) 使用这些参数调用超级构造函数。这导致了样板代码:大量重复,使代码更难阅读,维护起来更麻烦。

一些Dart社区成员帮助实现这一目标。GitHub用户@roy-sianez大约半年前就此提出了语言问题;建议类似于 GitHub 用户 @apps-transround 之前的建议:我们也许可以通过引入一个新结构来表达在超类中指定了参数来解决这个问题。我们认为这是一个好主意,所以它被添加到Dart 2.17中。从下面的例子中可以看出,这与 Flutter widget 代码尤其相关。事实上,当我们将新功能应用于 Flutter 框架时,我们看到总共减少了近两千行代码

img

到处都是命名的参数

最后,我们改进了调用方法时命名参数的工作方式。以前,这些必须出现在方法的参数列表中的最后。如果您希望将位置参数放在最后以使代码更具可读性,这很烦人。例如,请参阅以下构造函数的调用 — 以前,可增长参数必须放在最后,因此很容易错过包含生成器本身的大型位置参数下方。现在,您可以根据需要对它们进行排序,从而允许您将小命名参数放在第一位,生成器放在最后。List.generate

img

有关操作中这三个功能的更多示例,请参阅枚举超级初始值设定项命名参数的更新示例。

生产力工具

延续生产力主题,我们对核心工具进行了一些改进。

在 Dart 2.14 中,我们引入了 ,它与 Dart 分析器配合使用,可帮助您编写 Dart 代码,以防止错误,并使用规范样式实现更有效的代码审查。从那以后,分析器中提供了许多新的 lint,我们仔细地对这些 lint 进行了分类,并从中为所有 Dart 代码选择了 10 个新 lint,以及两个专门用于 Flutter 代码的新 lint。其中包括用于确保导入包含在 pubspec 文件中的 lints,防止对类型参数滥用 null 检查,以及确保子属性的样式一致。您可以使用一个简单的命令升级到新的 lints:package:lints

  • 对于飞镖套餐:
    dart pub upgrade —-major-versions lints
  • 对于颤振包:
    flutter pub upgrade —-major-versions flutter_lints

SecureSockets 通常用于启用使用 TLS 和 SSL 保护的 TCP 套接字。在 Dart 2.17 之前,在开发过程中调试这些套接字很棘手,因为无法检查安全数据流量。现在,我们添加了对指定文件的支持。如果指定,则在与服务器交换新的 TLS 密钥时,会将 NSS 密钥日志格式的文本行追加到文件中。这使网络流量分析器工具(如 Wireshark)能够解密通过套接字发送的内容。有关详细信息,请参阅 的 API 文档。keyLog``SecureSocket.connect()

该工具生成的 API 文档是大多数学习新 API 的 Dart 开发人员的关键资产。虽然我们的核心库 API 长期以来一直具有丰富的文本描述,但许多开发人员告诉我们,他们更喜欢通过阅读使用 API 的示例代码来学习 API。在 Dart 2.17 中,我们彻底改革了所有主要的核心库,将示例代码添加到前 200 个浏览量最大的页面中,因此它们现在拥有了全面的示例代码。例如,将 Dart 2.16 中 dart:convert 的文档与 Dart 2.17 的更新页面进行比较;希望这使文档更易于使用。dart doc

生产力的提高不仅体现在我们向平台添加新功能时,而且当我们清理堆栈并删除不再使用的功能时也是如此。这有助于保持我们的表面积较小,这对新开发人员尤其重要。为此,我们从库中删除了 231 行已弃用的代码 — 如果您仍在使用这些已弃用的 API,则可以使用 .我们还继续努力删除已弃用的 Dart CLI 工具,这次删除了该工具(改用)和工具(使用或)。dart:io``dart fix``dartdoc``dart doc``pub``dart pub``flutter pub

扩大我们的平台集成和支持

第二个核心主题是平台集成和支持。Dart是一种真正的多平台语言。虽然我们已经支持广泛的平台,但我们在不断发展,以确保您可以与每个受支持的平台深度集成,并支持新兴平台

Dart FFI — 我们与 C/本机代码互操作的核心机制 — 是将 Dart 代码与现有本机平台代码集成的一种流行方式。在 Flutter 上,这可能是构建使用主机平台本机 API 的插件(例如 Windows win32 API)的好方法。在 Dart 2.17 和 Flutter 3 中,我们向该工具添加了模板,因此您现在可以轻松创建具有 Dart API 支持的 FFI 插件,这些插件由调用本机代码提供支持。有关详细信息,请参阅 flutter.dev 上更新的开发包和插件页面。flutter``dart:ffi

为了在具有特定于其 ABI(应用程序二进制接口)类型的平台上使用 FFI,FFI 现在支持 ABI 特定类型。例如,您现在可以使用 ( 在 C 中)正确表示具有 ABI 特定大小的长整数,该大小可能是 32 位或 64 位,具体取决于 CPU 体系结构。有关支持类型的完整列表,请参阅 API 页面中的“实施者”列表。Long``long``AbiSpecificInteger

在使用 Dart FFI 与本机平台深度集成时,有时需要对齐 Dart 分配的内存或其他资源(端口、文件等)的清理和本机代码。这在历史上是非常棘手的,因为Dart是一种自动处理清理的垃圾回收语言。Dart 2.17 通过引入终结器的概念解决了这个问题,它包括一个标记接口,用于“标记”不应过早完成或丢弃的对象,以及一个可以附加到 Dart 对象的类,以便在对象即将被垃圾回收时提供回调运行。这些共同允许在本机代码和 Dart 代码中运行清理代码。有关详细信息,请参阅 API 文档中的说明和示例,或常规 Dart 代码中类似支持的文档。Finalizable``NativeFinalizer``NativeFinalizer``WeakReferences``Finalizer

我们对将 Dart 编译为本机代码的支持是使 Flutter 应用程序具有出色的启动性能和快速渲染的核心推动因素。第二个用例是能够使用 .这些可执行文件可以在任何计算机上独立运行,而无需安装 Dart SDK。Dart 2.17 中的另一个新功能是支持可执行文件的签名,这允许在通常需要签名的 Windows 和 macOS 上进行部署。dart compile

我们还将继续扩大我们支持的平台集,保持在新兴平台的最前沿。RISC-V是用于处理器的新型创新指令集。RISC-V International是一家全球性的非营利组织,拥有RISC-V规范,使指令集自由开放。这仍然是一个新兴平台,但我们对它的潜力感到兴奋,因此我们的 Linux 版本(或我们的测试版的更高版本)包括对它的实验性支持。我们很乐意听到您的反馈,因此请提交问题发布有关您的体验的信息!2.17.0–266.1.beta

开始使用 Dart 2.17!

我们希望今天的 Dart 2.17 版本能让您兴奋不已,提高您的工作效率,并为您的应用程序实现更多的平台集成。要开始使用,您可以直接下载 Dart 2.17 版本,或将其作为今天 Flutter 3 SDK 版本的一部分嵌入。

我们还邀请您查看我们为 Google I/O 提供的新内容

Dart 2.16:改进的工具和平台处理

通过包平台标记和新的 pub.dev 搜索体验支持 Windows 版 Flutter

今天,Dart SDK版本2.16可用。它没有新的语言功能,但修复了一堆错误(包括对安全漏洞的修复),改进了对指定 Dart 包支持的平台的支持,以及全新的 pub.dev 搜索体验。

飞镖 2.16

今天与 Flutter 2.10 一起推出的 Dart 2.16 SDK 继续从传统的 Dart CLI 工具(等)过渡到新的组合开发人员工具。新弃用的工具是 (使用 ) 和 (使用 )。在 Dart 2.17 中,我们计划完全删除 、 和 命令(在 Dart 2.15 中已弃用;使用 or )。有关详细信息,请参阅问题 #46100dartfmt``dartdoc``dart``dartdoc``dart doc``dartanalyzer``dart analyze``dartdoc``dartanalyzer``pub``dart pub``flutter pub

2.16 版本还包括对一个安全漏洞和两个小的重大更改的修复:

  • 中的 API 允许您为 、、 和 设置可选标头。在 Dart 2.16 之前的 SDK 中实现重定向逻辑存在一个漏洞,即在发生跨源重定向时传递这些标头(可能包含敏感信息)。在 Dart 2.16 中,这些标头被丢弃。有关详细信息,请参阅 CVE-2022–0451HttpClient``dart:io``authorization``www-authenticate``cookie``cookie2
  • 中的 API 在 Windows 上的行为已更改:它不再删除与目标名称匹配的现有目录(问题 #47653)。Directory.rename``dart:io
  • 和 API(Dart 1.x 遗留下来的、在 Dart 2.x 中不起作用)已被删除(问题 #47769)。Platform.packageRoot``Isolate.packageRoot

要查找有关 Dart 2.16 中更改的更多详细信息,请参阅更改日志

对声明 pub.dev 包的平台支持的新支持

Dart 专为可移植性而设计,我们努力支持在尽可能多的平台上运行的代码。但是,有时您可能会在仅为一个或几个平台设计的 pub.dev 上创建和共享包。你可能有一个包依赖于仅在特定操作系统上可用的 API,或者一个包使用仅在本机平台上不受支持而不是在 Web 上支持的库。dart:ffi

在 Dart 2.16 中,您现在可以在软件包的 pubspec 中手动声明一组受支持的平台。例如,如果您的软件包仅支持 Windows 和 macOS,则其文件可能如下所示:pubspec.yaml

name: mypackage
version: 1.0.0platforms:
  windows:
  macos:dependencies:

新标记适用于以下情况:您正在开发 Dart 包,并且您希望声明对一组与 pub.dev 自动检测的平台不同的平台的支持。如果您正在开发和共享包含主机特定代码(例如 Kotlin 或 Swift)的 Flutter 插件,则 Flutter 插件标签通常会指定支持的平台。platforms

新的 pub.dev 搜索用户界面

为了响应开发人员的请求,我们为在 pub.dev 上搜索包创建了更好的支持。今天推出的更改的主要目标是帮助您识别和搜索一组受支持的平台。下面是新搜索体验的视图:

img

Pub.dev 搜索界面,侧边栏包含平台、SDK 和高级搜索过滤器

新的搜索 UI 左侧有一个搜索筛选器侧边栏,可用于限制包搜索:

  • 平台:选择一个或多个平台,将搜索结果范围缩小到仅支持所选平台的所有包。
  • SDK:选择 Dart 或 Flutter 以将结果分别限制为支持 Dart SDK 或 Flutter SDK 的包。
  • 高级:其他搜索选项,例如筛选到颤振收藏夹包。

空安全更新

自从我们上次讨论空安全以来已经发布了几个版本,空安全是一年前在Dart 2.12中推出的主要语言添加。我们对 Dart 生态系统迁移软件包以支持空安全的速度感到惊讶:截至今天,前 250 个软件包中的 100% 以及前 1000 个软件包中的 96% 支持空安全!感谢所有为这一伟大成就做出贡献的软件包作者。

我们还看到应用迁移到声音空安全(应用代码和所有包依赖项已迁移的状态)的良好进展。根据我们的分析,Flutter 工具中 71% 的运行会话现在具有完全的声音零安全性。如果您是应用开发人员,但仍未迁移,那么现在正是绝佳时机。

结语

我们希望你发现新的 pub.dev 搜索 UI 有用,我们欢迎你提供任何反馈。请继续关注定于 2022 年第二季度发布的下一个 Dart SDK 版本。我们正在开发几个令人兴奋的语言功能,我们希望在今年晚些时候发布。

宣布飞镖 2.15

快速并发、构造函数撕裂、改进的枚举等

今天,我们将发布 Dart SDK 的 2.15 版,它具有与工作线程隔离的快速并发性、新的构造函数撕除语言功能、改进的 dart:core 库中的枚举支持、包发布者的新功能等。

列出 2.15 新功能的图形

与工作线程隔离的快速并发

几乎所有现代设备都有具有多个内核的CPU,能够并行运行多个任务。对于大多数 Dart 程序,如何使用这些内核对开发人员是透明的:默认情况下,Dart 运行时系统在单个内核上运行所有 Dart 代码,但随后使用其他内核执行系统级任务,例如异步输入/输出,例如写入文件或进行网络调用。

但是您的 Dart 代码本身可能需要同时运行。例如,您可能有一个连续的动画和一个长时间运行的任务,例如解析大型 JSON 文件。如果附加任务花费的时间过长,则可能会导致 UI 出现卡顿或滞后。通过将这些附加任务移动到单独的内核,动画可以继续在执行的主线程上运行,而不会中断。

Dart的并发模型基于隔离(彼此隔离的独立执行单元),以防止与共享内存相关的大量并发编程错误,例如数据竞争等竞争条件。Dart 通过不允许在隔离器之间共享任何可变对象来防止这些错误,而是使用一个模型,其中使用消息传递隔离交换状态。在 Dart 2.15 中,我们对隔离进行了许多实质性的增强。

我们首先重新设计和重新实现隔离的工作方式,引入了一个新概念:隔离组。 隔离组中的隔离共享表示正在运行的程序的各种内部数据结构 这使得组中的单个分离株便宜得多。现在,在现有隔离组中启动额外的隔离的速度提高了 100 倍以上,因为我们不需要初始化程序结构,并且这些生成的隔离消耗的内存减少了 10-100 倍。

虽然隔离组仍会阻止在隔离之间共享访问可变对象,但该组是使用共享堆实现的,从而解锁了更多功能。我们可以将对象从一个隔离传递到另一个隔离,这些隔离可用于执行返回大块内存的任务的工作线程隔离。例如,工作线程隔离进行网络调用以获取数据,将该数据解析为大型 JSON 对象图,然后将该 JSON 图返回到主隔离。在 Dart 2.15 之前,需要深度复制该结果,如果复制花费的时间超过帧预算,这本身可能会导致 UI 卡顿。

在 2.15 中,工作线程隔离可以调用 ,将其结果作为参数传递。然后,Dart 运行时将包含结果的内存从工作线程隔离传递到主隔离,而不进行复制,并且主隔离可以在恒定时间内接收结果。我们更新了 Flutter 2.8 中的实用程序功能以利用 .如果您已经在使用 ,那么在升级到 Flutter 2.8 后,您将自动获得这些性能提升。Isolate.exit()``compute()``Isolate.exit()``compute()

最后,我们重新设计了隔离消息传递机制的实现方式,使中小型消息的传递速度提高了大约 8 倍。发送速度明显更快,并且接收消息几乎总是在恒定的时间内完成。我们还扩展了隔离可以相互发送的对象类型,增加了对函数类型、闭包和堆栈跟踪对象的支持。有关详细信息,请参阅 的 API 文档。SendPort.send()

若要了解有关如何使用隔离的详细信息,请参阅我们为 2.15 添加的新 Dart 中的并发文档。我们还有许多代码示例可供您查看。

新的语言功能:构造函数撕下

在 Dart 中,可以使用函数的名称创建一个函数对象,该对象指向另一个对象上的函数。在下面的示例中,main() 方法的第二行在将“g”设置为“m.greet”时说明了此语法:

class Greeter {
  final String name;
  Greeter(this.name);

  void greet(String who) {
    print('$name says: Hello $who!');
  }
}void main() {
  final m = Greeter('Michael');
  final g = m.greet; // g holds a function pointer to m.greet.
  g('Leaf'); // Invokes and prints "Michael says: Hello Leaf!"
}

此类函数指针(也称为函数撕裂)在使用 Dart 核心库时经常出现。下面是通过向可迭代对象传递函数指针来调用可迭代对象的示例:foreach()

final m = Greeter('Michael');['Lasse', 'Bob', 'Erik'].forEach(m.greet);// Prints "Michael says: Hello Lasse!", "Michael says: Hello Bob!",
// "Michael says: Hello Erik!"

从历史上看,我们不支持从构造函数创建撕裂(语言问题 #216)。这很烦人,因为在许多情况下 – 例如,在构建 Flutter UI 时 – 构造函数撕掉是你需要的。从 Dart 2.15 开始,现在支持此语法。下面是一个构建包含三个小部件的小部件的示例,方法是调用它并将其撕下传递给 的构造函数。Column``Text``.map()``Text

class FruitWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
        children: ['Apple', 'Orange'].map(Text.new).toList());
  }
}
Text.new`引用类的默认构造函数。还可以引用命名构造函数,例如 。`Text``.map(Text.rich)

相关语言更改

在实现构造函数撕下时,我们借此机会修复了对函数指针的现有支持中的一些不一致之处。现在,您可以将泛型方法专用化为创建非泛型方法:

T id(T value) => value;
var intId = id; // New in 2.15.
int Function(int) intId = id; // Pre-2.15 workaround.

您甚至可以专门化泛型函数对象来创建非泛型函数对象:

const fo = id; // Tear off `id`, creating a function object.
const c1 = fo; // New in 2.15; error before.

最后,我们清理了涉及泛型的类型文字:

var y = List; // Already supported.
var z = List; // New in 2.15.
var z = typeOf>(); // Pre-2.15 workaround.

改进了 dart:core 库中的枚举

我们对 dart:core 库中的枚举 API 进行了一些方便的添加(语言问题 #1511)。现在,您可以使用以下命令获取每个枚举值的值:String``.name

enum MyEnum {
  one, two, three
}void main() {
  print(MyEnum.one.name);  // Prints "one".
}

您还可以按名称查找枚举值:

print(MyEnum.values.byName('two') == MyEnum.two);  // Prints "true".

最后,您可以获得所有名称-值对的映射:

final map = MyEnum.values.asNameMap(); 
print(map['three'] == MyEnum.three);  // Prints "true".

有关使用这些新 API 的示例,请参阅此 Flutter PR。

压缩指针

Dart 2.15 添加了对压缩指针的支持,如果只需要支持 32 位地址空间(最多 4 GB 内存),则 64 位 SDK 可以使用更节省空间的指针表示形式。压缩指针会导致内存显著减少;在 GPay 应用程序的内部测试中,我们看到 Dart 堆大小减少了大约 10%。

由于压缩指针意味着无法寻址 4 GB 以上的任何可用 RAM,因此该功能位于 Dart SDK 中的配置选项后面,该选项只能在构建 SDK 时由 Dart SDK 的嵌入器切换。Flutter SDK 版本 2.8 已为 Android 构建启用此配置,Flutter 团队正在考虑在未来版本中为 iOS 构建启用此配置。

Dart SDK 中包含的 Dart DevTools

DevTools 调试和性能工具套件以前不在 Dart SDK 中;您必须单独下载它。从 Dart 2.15 开始,现在在下载 Dart SDK 时可以获得 DevTools,无需进一步的安装步骤。有关将 DevTools 与 Dart 命令行应用配合使用的详细信息,请参阅 DevTools 文档

面向包发布者的新发布功能

Dart 2.15 SDK 在开发人员命令和 pub.dev 包存储库中还具有两个新功能。dart pub

首先,包发布者有一项新的安全功能。目的是检测发布者何时意外在发布包中发布机密(例如云或 CI 凭据)。在了解到在 GitHub 存储库中,每天都有数千个机密泄露后,我们受到启发,添加了此泄漏检测。

泄漏检测作为命令中预发布验证运行的一部分运行。如果它在即将发布的文件中检测到潜在的机密,则该命令将退出而不发布,并打印如下输出:dart pub publish``publish

Publishing my_package 1.0.0 to https://pub.dartlang.org:
Package validation found the following errors:
* line 1, column 1 of lib/key.pem: Potential leak of Private Key detected.
╷
1 │ ┌ - - -BEGIN PRIVATE KEY - - -
2 │ │ H0M6xpM2q+53wmsN/eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ
3 │ └ - - -END PRIVATE KEY - - -
╵
* line 2, column 23 of lib/my_package.dart: Potential leak of Google OAuth Refresh Token detected.
╷
2 │ final refreshToken = "1//042ys8uoFwZrkCgYIARAAGAQSNwF-L9IrXmFYE-sfKefSpoCnyqEcsHX97Y90KY-p8TPYPPnY2IPgRXdy0QeVw7URuF5u9oUeIF0";

在极少数情况下,此检测可能会有误报,标记您实际打算发布的内容或文件的潜在泄漏。在这些情况下,您可以将文件添加到允许列表

其次,我们为发布者添加了另一项功能,该功能支持收回已发布的包版本。发布错误的包版本时,我们通常建议发布具有较小增量的新版本,以修复意外问题。在极少数情况下,例如,当您还没有这样的修复程序,或者您不小心发布了一个新的主要版本但打算发布新的次要版本时,您可以使用新的软件包撤回功能作为最后的手段。此功能在 pub.dev 上的管理 UI 中可用:

包撤回 UI 的屏幕截图

收回软件包版本后,pub 客户端不再解析为 or 中的该版本。如果任何开发人员已经解析为撤回版本(因此在他们的文件中),他们将在下次运行时看到警告:pub get``pub upgrade``pubspec.lock``pub

$ dart pub get
Resolving dependencies…
mypkg 0.0.181-buggy (retracted, 0.0.182-fixed available)
Got dependencies!

用于检测双向 Unicode 字符的安全性分析 (CVE-2021–22567)

最近发现了一个涉及双向 Unicode 字符的通用编程语言漏洞 (CVE-2021–42574)。此漏洞会影响支持 Unicode 的大多数现代编程语言。以下 Dart 源代码说明了该问题:

main() {
  final accessLevel = 'user';  if (accessLevel == 'user‮ .⁦// Check if admin⁩ ⁦') {
    print('You are a regular user.');
  } else {
    print('You are an admin.');
  }
}

您可能会认为该程序打印“您是普通用户”,但实际上可能会打印“您是管理员”!通过使用包含双向 Unicode 字符的字符串,可以利用此漏洞。这些字符将文本的方向从左到右更改为从右到左和向后,所有这些都在一行内。使用双向字符,文本在屏幕上的呈现方式可能与实际文本内容大不相同。您可以在此 GitHub 代码要点中看到一个示例。

针对此漏洞的缓解措施包括使用检测双向 Unicode 字符的工具(编辑器、代码审查工具等),以便开发人员可以了解它们,并有意接受它们的使用。上面链接的 GitHub gist 文件查看器是显示这些字符的工具的一个示例。

Dart 2.15 引入了进一步的缓解措施(Dart 安全通报 CVE-2021–22567):Dart 分析器现在扫描双向 Unicode 字符,并标记对它们的任何使用:

$ dart analyze
Analyzing cvetest...                   2.6sinfo • bin/cvetest.dart:4:27 • The Unicode code point 'U+202E'
       changes the appearance of text from how it's interpreted
       by the compiler. Try removing the code point or using the 
       Unicode escape sequence '\u202E'. •
       text_direction_code_point_in_literal

我们建议将这些字符替换为 Unicode 转义序列,以便它们在任何文本编辑器或查看器中可见。或者,如果您确实合法使用这些字符,则可以通过在使用前面的行中添加覆盖来禁用警告:

// ignore: text_direction_code_point_in_literal

使用第三方发布服务器时 Pub.dev 凭据漏洞 (CVE-2021–22568)

我们还将发布第二条与 pub.dev 相关的 Dart 安全公告:CVE-2021–22568。此通报面向可能已将程序包发布到第三方发布程序包服务器(如专用或公司内部程序包服务器)的程序包发布者。仅发布到公共 pub.dev 存储库(标准配置)的开发人员不受此漏洞的影响

如果您已发布到第三方存储库,则漏洞在于在该第三方存储库中提供的用于身份验证的 OAuth2 临时(一小时)访问令牌可能被滥用,以针对公共 pub.dev 存储库进行身份验证。因此,恶意的第三方发布服务器可能会使用访问令牌在 pub.dev 上模拟您并在那里发布包。如果您已将包发布到不受信任的第三方包存储库,请考虑对 pub.dev 公共包存储库上的所有帐户活动进行审核。为此,可以使用 pub.dev 活动日志

结语

我们希望您能喜欢今天推出的 Dart 2.15 中的新功能。这是我们今年的最后一个版本,我们想借此机会对精彩的Dart生态系统表示感谢。感谢所有出色的反馈,感谢我们的持续增长所见证的持续支持,以及在过去一年中通过 pub.dev 上发布的数千个软件包扩展我们的生态系统。我们迫不及待地想在明年回到这个问题,我们在 2022 年计划了很多令人兴奋的事情。在那之前,享受假期!

https://medium.com/tag/programming?source=post_page—–7e7a598e508a—————programming—————–)

宣布飞镖 2.14

Apple Silicon 支持,并通过默认 lint 、更好的工具和新的语言功能提高了工作效率

今天,我们将发布 Dart SDK 的 2.14 版,这是我们正在进行的旅程中的下一个版本,旨在通过可移植性、生产力和健壮性的独特组合,为构建应用程序提供最佳平台。这一次,我们对 Apple Silicon 有了更好的支持,以及许多生产力增强功能,例如用于在编写代码时通过代码样式分析捕获错误的标准 lints、更快的 pub 工具、使用级联更好地格式化代码,以及一些小语言功能。

带有总结 2.14 新功能的文本插图

Dart SDK 中的 Apple 芯片支持

自 Apple 于 2020 年底宣布推出新的 Apple 芯片处理器以来,我们一直致力于更新 Dart SDK,以添加新处理器上本机执行的支持。所需的更改在开发频道中已经有一段时间了,在过去的一个月里在测试版频道中可用,从 Dart 2.14.1 开始,现在在 Dart 稳定频道中可用。下载 macOS SDK 时,请确保选择 ARM64 选项。请注意,Flutter SDK 中捆绑的 Dart SDK 还没有这些改进。

该支持包括在 Apple Silicon 上运行 SDK/Dart VM 本身,以及支持编译在 Apple Silicon 上运行的可执行文件(使用 )。Dart命令行工具现在使用本机Apple Silicon支持,因此启动速度要快得多。dart compile

Dart和Flutter共享的标准棉绒

开发人员通常更喜欢他们的代码遵循某种风格。其中许多规则不仅仅是样式首选项(例如众所周知的选项卡与空格讨论),而是涵盖了可能导致错误或引入错误的编码样式。例如,Dart 样式指南要求对所有控制流结构(如 if-else 语句)使用大括号。这可以防止经典的悬空 else 问题,即在如何解释多个嵌套的 if-else 语句方面存在歧义。另一个例子是类型推断。虽然在声明具有初始值的变量时使用类型推断是可以的,但在声明未初始化的变量时指定类型以确保类型安全非常重要。

实施良好代码风格的一种选择是进行某种形式的人工强制,通常是通过代码审查。但是,通过在编写代码时运行的静态分析来强制实施规则通常更有效。

在 Dart 中,这种静态分析是高度可配置的,我们有数百个样式规则(也称为 lints)。有了这么多丰富的选项,选择要启用的规则可能会有点不知所措。Dart 团队维护着一个 Dart 风格指南,它描述了我们认为编写和设计 Dart 代码的最佳方式,但从历史上看,我们没有一套与风格指南相对应的官方 linter 规则。

许多开发人员 – 以及 pub.dev 网站评分引擎 – 都使用了迂腐的lint规则集。然而,Pedantic起源于Google内部的Dart风格指南,由于历史原因,该指南与一般的Dart风格指南不同。此外,Flutter 框架从未使用过迂腐的规则集,而是有自己的一套规范规则。

这听起来可能有点混乱,确实如此。但是在今天的版本中,我们很高兴地宣布,我们现在有一组全新的 lint 集合来实现样式指南,并且 Dart 和 Flutter SDK 已更新为默认将这些规则集用于新项目。规则集包括:

  • package:lints/core.yamlDart风格指南中的主要规则,我们认为所有Dart代码都应该遵循。pub.dev 评分引擎已更新为使用这些而不是迂腐。
  • package:lints/recommended.yaml核心规则,以及其他建议的规则。建议将此集合用于所有常规 Dart 代码。
  • package:flutter_lints/flutter.yaml:核心规则和推荐规则,以及其他特定于 Flutter 的推荐规则。建议所有 Flutter 代码使用此集合。

如果您有现有项目,我们强烈建议您升级到这些新规则集。从迂腐升级只需几个步骤

飞镖格式化程序和级联

我们对 Dart 格式化程序如何使用级联格式化代码进行了一些优化。以前,格式化程序在某些情况下会产生令人困惑的格式。例如,此示例中调用了什么?doIt()

var result = errorState ? foo : bad..doIt();

它可能看起来像总是被调用,但实际上级联适用于整个表达式,因此级联是根据该表达式的结果调用的,而不仅仅是在 false 子句上。新的格式化程序清楚地表明了这一点:bad``?

var result = errorState ? foo : bad
  ..doIt();

其他更改涉及具有多个级联的行的格式设置方式,以及级联通常缩进的距离。我们还大大提高了格式化包含级联的代码的速度;在为协议缓冲区生成的 Dart 代码中,我们看到格式化速度提高了 10 倍。

有关所有详细信息,请参阅跟踪问题

对忽略文件的 pub 支持

目前,当您将软件包发布pub.dev 社区存储库时,pub 会抓取该文件夹中的所有文件,但有一些例外,跳过隐藏文件(以点开头的文件:)和 中列出的文件。一些开发人员要求能够控制在 中的列表之外忽略哪些文件。例如,你可能在用于维护包的文件夹中有一些内部开发工具,但这些工具与使用你的包的人员无关。.``.gitignore``.gitignore``tool/

Dart 2.14 中更新的 pub 命令支持一个新文件,您可以在其中列出不想上传到 pub.dev 的文件。此文件使用与文件相同的格式。有关详细信息,请参阅包发布文档.pubignore``.gitignore

酒吧和“飞镖测试”性能

虽然 pub 可能最常用于管理代码依赖项,但它还有第二个重要的实用程序:为工具提供支持。一个这样的例子是通过命令公开的 Dart 测试工具。此命令实际上只是 的包装器,它运行 中的入口点。在调用该入口点之前,pub 首先将其编译为可以运行得更快的本机代码。dart test``command pub run test:test``test``package:test

在 Dart 2.14 之前,对 pubspec 的任何更改(包括与 无关的更改)都会使此测试版本无效,并且您会看到一堆包含“预编译可执行文件”的输出:package:test

$ dart test
Precompiling executable... (11.6s)
Precompiled test:test.
00:01 +1: All tests passed!

在 Dart 2.14 中,pub 在何时使构建步骤失效方面要聪明得多,因此只有在版本更改时才会进行构建。此外,我们改进了使用并行化执行该构建步骤的方式,因此步骤本身的完成速度要快得多。我们已经看到,在我们测试过的某些软件包上,它花费了一半的时间。

新的语言功能

Dart 2.14 还包含许多小语言功能。这一次,我们专注于更具体的改进,这些改进可能具有更窄的效用,但支持以前不支持的更专业的用例。

首先,我们添加了一个新的三班运算符 ()。这类似于现有的移位运算符 (),但是 其中执行算术移位,执行逻辑或无符号移位,其中零位移位到最高有效位,而不管要移位的数字是正数还是负数。>>>``>>``>>``>>>

我们还删除了对类型参数的旧限制,该限制不允许使用泛型函数类型作为类型参数。以下所有操作在 2.14 之前都是无效的,但现在是允许的:

late List<T Function<T>(T)> idFunctions;
var callback = [<T>(T value) => value];
late S Function<S extends T Function<T>(T)>(S) f;

最后,我们对注释类型进行了小的调整。(Dart 代码中通常用于捕获元数据的注释。以前,注释不能传递类型参数,因此不允许使用类似代码。此限制现已删除。@Deprecated``@TypeHelper(42, "The meaning")

包和核心库更改

我们对核心 Dart 包和库进行了许多增强,包括:

  • dart:core:向类中添加了静态方法 、 和。这些可用于以一致的方式组合多个对象的哈希代码(hashAll示例)。hash``hashAll``hashAllUnordered``Object
  • dart:core:本机类现在可以更好地处理夏令时更改(不精确为一小时)的本地时间 – 例如澳大利亚的豪勋爵岛,它使用 30 分钟的班次。DateTime
  • package:ffi:添加了对使用竞技场分配器管理内存的支持(示例)。竞技场是一种基于区域的内存管理形式,一旦竞技场/区域退出,资源就会自动释放。
  • package:ffigen:现在支持从 C typedefs 生成 Dart typedef。

中断性变更

Dart 2.14 还包含许多较小的、先前宣布的中断性更改。预计这些更改只会影响几个专门的用例。

#46545: 删除了对 ECMAScript5 的支持

所有现代浏览器都支持最新的 ECMAScript 版本,因此两年前我们宣布了一项计划,弃用对 ECMAScript 5 (ES5) 的支持。这使我们能够利用最新 ECMAScript 中的改进并生成更小的输出。在Dart 2.14中,这项工作已经完成,Dart Web编译器不再支持ES5。因此,不再支持较旧的浏览器(如 IE11)。

#46100:弃用舞台手、dartfmt 和 dart2native

在 2020 年 10 月的 Dart 2.10 博客文章中,我们宣布了将所有 Dart CLI 开发人员工具合并到一个组合工具(类似于该工具)的工作。作为该演变的一部分,Dart 2.14弃用了前者和命令,并停止了。这些工具在统一 工具中都有等效的替换项。dart``flutter``dartfmt``dart2native``stagehand``dart

#45451:弃用虚拟机本机扩展

我们已弃用 Dart VM 的本机扩展,这是我们从 Dart 代码调用本机代码的旧机制。Dart FFI(外部函数接口)是我们目前针对此用例的机制,我们正在积极发展它,使其更加强大和易于使用。

空安全更新

我们在 3 月份的 Dart 2.12 版本中推出了声音零安全。空安全是 Dart 最新的主要生产力功能,旨在帮助您避免空错误——一类通常很难发现的错误。

自上次更新以来,我们在迁移现有软件包和应用程序方面取得了巨大进展,以实现空安全的声音检查优势。对于 pub.dev 上的软件包,前 250 个软件包中的 100% 现在支持 null 安全,前 1000 个软件包中有 94% 支持空安全。这意味着更多的开发人员可以在完全安全的情况下运行他们的应用程序。分析显示,56% 的会话完全稳健地执行。感谢生态系统中的所有开发人员的迁移工作!flutter run

2.14 可用性和持续势头

包含上述更改的增强型 Dart SDK 现已在 Dart 2.14.1 和 Flutter 2.5 SDK 中提供。我们希望您会喜欢新的增强功能和功能。

此外,我们想借此机会向令人敬畏的Dart社区表示感谢。正如最近对编程语言调查的一些更新所证明的那样,Dart的势头强劲。备受尊敬的RedMonk排名提到了“Dart的非凡崛起”,并首次将Dart置于前20名。StackOverflow 的 2021 年综合开发者调查同样令人愉快:据报道,Dart 是开发人员喜爱的第 7 种编程语言。我们真的很高兴看到Dart平台持续增长和势头。

宣布飞镖 2.13

新的类型别名语言功能,改进了飞镖FFI

显示本文内容亮点的图形:类型别名,更好的FFI,空安全性,Docker支持

作者:Kevin Moore & Michael Thomsen

今天,我们宣布推出 Dart 2.13,它具有类型别名 — 目前我们请求最多的语言功能。Dart 2.13 还包括改进的 Dart FFI 和更好的性能,我们有新的 Docker 官方镜像。这篇文章提供了 2.12 中引入的空安全功能的更新,讨论了新的 2.13 功能,有一些关于 Docker 和 Google Cloud 对 Dart 后端的支持的令人兴奋的消息,并预览了一些您可以在未来版本中看到的变化。

空安全更新

我们在 3 月份的 Dart 2.12 版本中推出了声音零安全。空安全是 Dart 最新的主要生产力功能,旨在帮助您避免空错误——一类通常很难发现的错误。通过此次发布,我们鼓励软件包发布者开始迁移共享软件包,pub.dev 到空安全。

我们非常高兴地看到空安全被采用的速度如此之快!在发布几个月后,pub.dev 上最受欢迎的 500 个软件包中有 93% 已经支持空安全。我们要衷心感谢所有软件包开发人员如此迅速地完成这项工作,并帮助整个生态系统向前发展!

有这么多包支持空安全,你很有可能开始迁移你的应用以使用空安全。第一步是用于检查应用的依赖项。有关详细信息,请参阅空安全迁移指南。我们还更改了 和 模板,以便它们现在默认在新应用和程序包中启用 null 安全性。dart pub outdated``dart create``flutter create

宣布类型别名

类型别名是 2.13 语言中的新功能。它扩展了我们早期的支持,允许创建函数类型的类型别名,但不允许创建任何其他类型。这个备受追捧的功能在语言问题跟踪器中排名第二。

使用类型别名,可以为任何现有类型创建新名称,然后可以在可以使用原始类型的任何位置使用该名称。您并没有真正定义一个新类型,只是引入了一个简写别名。别名甚至通过了类型相等性测试:

typedef Integer = int;void main() {
  print(int == Integer); // true
}

那么可以使用类型别名做什么呢?一种常见的用途是为类型提供更短或更具描述性的名称,从而使代码更具可读性和可维护性。

一个很好的例子是使用JSON(感谢GitHub用户Levi-Lesches的这个例子)。在这里我们可以定义一个新的类型别名,它将 JSON 文档描述为从键到任何值(使用该类型)的映射。然后,我们可以在定义命名构造函数和 getter 时使用该类型别名。Json``String``dynamic``Json``fromJson``json

typedef Json = Map<String, dynamic>;class User {
  final String name;
  final int age;  User.fromJson(Json json) :
    name = json['name'],
    age = json['age'];Json get json => {
    'name': name,
    'age': age,
  };
}

您还可以在命名类的类型别名上调用构造函数,因此以下内容是完全合法的:

main() {
  var j = Json();
  j['name'] = 'Michael';
}

通过使用类型别名为复杂类型命名,可以使读者更容易理解代码的不变量。例如,下面的代码定义一个类型别名来描述包含泛型类型的键和类型值的映射。通过使用单个类型参数为类型指定名称,映射的常规结构对于代码的读者来说变得更加明显。X``List

typedef MapToList<X> = Map<X, List<X>>;
void main() {
  MapToList<int> m = {};
  m[7] = [7]; // OK
  m[8] = [2, 2, 2]; // OK
  for (var x in m.keys) {
    print('$x --> ${m[x]}');
  }
}=>7 --> [7]
8 --> [2, 2, 2]

如果尝试使用不匹配的类型,则会出现分析错误:

m[42] = ['The', 'meaning', 'of', 'life'];=>The element type 'String' can't be assigned to the list type 'int'.

您甚至可以在重命名公共库中的类时使用类型别名。假设您在公共库中有一个要重命名为 的现有类。如果您只是重命名类,那么您的 API 客户将收到突然的编译错误。使用类型别名,您可以继续执行重命名,但随后为旧类名定义新的类型别名,然后为旧名称添加注释。使用 of 将在使用时发出警告,但将继续像以前一样编译和工作,让用户有时间升级他们的代码。PoorlyNamedClass``BetterNamedClass``@Deprecated``PoorlyNamedClass

下面介绍了如何实现和弃用(在名为 的文件中):BetterNamedClass``PoorlyNamedClass``mylibrary.dart

class BetterNamedClass {...}@Deprecated('Use BetterNamedClass instead')
typedef PoorlyNamedClass = BetterNamedClass;

以下是某人尝试使用的情况:PoorlyNamedClass

import 'mylibrary.dart';void main() {
  PoorlyNamedClass p;
}=>'PoorlyNamedClass' is deprecated and shouldn't be used. Use BetterNamedClass instead.

类型别名功能从 Dart 2.13 开始可用。要启用它,请将 pubspec 中的较低 Dart SDK 约束设置为至少 2.13:

environment:
  sdk: ">=2.13.0 <3.0.0"

由于语言版本控制,此功能向后兼容。在 2.13 下具有较低 SDK 约束的包可以安全地引用 2.13 包中定义的类型别名,即使 2.13 之前的包无法定义自己的类型别名也是如此。

飞镖 2.13 FFI 更改

我们在 Dart FFI 中也有几个新功能,这是我们用于调用 C 代码的互操作机制。

首先,FFI 现在支持具有内联数组的结构 (#35763)。考虑一个带有内联数组的 C 结构,如下所示:

struct MyStruct {
  uint8_t arr[8];
}

您现在可以直接将其包装在 Dart 中,使用类型参数指定元素类型:Array

class StructInlineArray extends Struct {
  @Array(8)
  external Array<Uint8> arr;
}

其次,FFI 现在支持打包结构 (#38158)。通常,结构布局在内存中,以便成员位于 CPU 更容易访问的地址边界中。对于打包结构,省略了某些填充以降低总体内存消耗,通常以特定于平台的方式。使用新批注,您可以轻松指定填充。例如,以下代码创建一个结构,该结构在内存中时具有 4 字节对齐方式:@Packed()

@Packed(4)
class TASKDIALOGCONFIG extends Struct {
  @Uint32()
  external int cbSize;
  @IntPtr()
  external int hwndParent;
  @IntPtr()
  external int hInstance;
  @Uint32()
  external int dwFlags;
  ...
}

飞镖 2.13 性能变化

我们将继续致力于减少 Dart 代码的应用程序大小和内存占用。在大型 Flutter 应用程序中,表示 AOT 编译的 Dart 程序元数据的内部结构可能会占用相当大的内存块。存在大多数元数据是为了启用热重载、交互式调试和人类可读堆栈跟踪格式等功能,这些功能在已部署的应用程序中从未使用过。在过去的一年中,我们一直在重组 Dart 本机运行时,以尽可能多地消除这种开销。其中一些改进适用于在发布模式下构建的所有 Flutter 应用程序,但有些改进要求您通过使用标志将调试信息从 AOT 编译的应用程序中分离出来来放弃人类可读的堆栈跟踪。--split-debug-info

Dart 2.13 包括许多更改,这些更改在使用时显著减少了程序元数据占用的空间。以Flutter Gallery应用程序为例。在Android上,带有调试信息的APK版本为112.4 MB,没有调试信息的APK为106.7 MB(总体减少5%)。这个APK包含很多资产。仅查看APK中的代码元数据,它从Dart 2.12中的5.7MB减少到Dart 2.13中的3.7MB(减少了35%)。--split-debug-info

如果应用大小和内存占用量对你很重要,请考虑使用标志省略调试信息。请注意,执行此操作时,您需要使用该命令使堆栈跟踪再次可读。--split-debug-info``symbolize

官方Docker支持和Google Cloud上的Dart

Dart现在作为Docker官方镜像提供。虽然 Dart 多年来一直提供 Docker 镜像,但这些新的 Dart 镜像经过 Docker 的测试和验证,以遵循最佳实践。它们还支持提前 (AOT) 编译,这可以显著减小构建容器的大小,并可以提高容器环境(如 Cloud Run)中的部署速度。

虽然Dart仍然专注于使像Flutter这样的应用程序框架能够在每个屏幕上驱动漂亮的像素,但我们意识到大多数用户体验的背后至少是一个托管服务。通过使用 Dart 轻松构建后端服务,我们支持全栈体验,允许开发人员使用与前端小部件相同的语言和业务逻辑将其应用程序扩展到云。

一般来说,将Dart用于Flutter应用程序后端特别适合Google托管无服务器平台Cloud Run的简单性和可扩展性。这包括缩放到零,这意味着当您的后端不处理任何请求时,您不会产生成本。我们与 Google Cloud 团队合作,提供 Functions Framework for Dart,这是一个包含软件包、工具和示例的集合,可以轻松编写要部署的 Dart 函数,而不是用于处理 HTTP 请求和 CloudEvents 的完整服务器。

查看我们的 Google Cloud 文档以开始使用。

关于下一步的几句话

我们已经在为即将发布的版本进行一些令人兴奋的更改。与往常一样,您可以使用语言漏斗跟踪器来关注我们的进度。

我们正在研究的一个领域是为Dart和Flutter提供一套新的规范棉绒。棉绒是配置 Dart 静态分析的一种强大方法,但由于有数百种可能的棉绒需要打开或关闭,因此很难决定选择什么。我们目前正在定义两组规范的 lints,我们将在 Dart 和 Flutter 项目中默认应用它们。我们希望在下一个稳定版本中默认启用此功能。如果您想预览,请查看两个软件包 lintsflutter_lints

最后,如果你对 Dart VM 运行时进行深度嵌入,请注意,我们计划为此弃用现有机制。我们将用基于 Dart FFI 的更快、更灵活的模型替换它(请参阅跟踪问题 #45451)。

Dart 2.13 现已上市

Dart 2.13 具有类型别名和改进的 FFI,现已在 Dart 2.13Flutter 2.2 SDK 中提供。

如果您一直在等待依赖项迁移到 null 安全性,则可能需要使用 .由于前 500 个最受欢迎的软件包中有 93% 已经迁移,因此您很有可能被解锁。我们还要非常感谢已经迁移的开发人员!dart pub outdated

我们很想听听您对这篇博文中讨论的新功能和更改的体验。在下面发表评论或@dart_lang发推文给我们。

宣布 Dart 支持 GitHub Actions

GitHub Actions 是 GitHub 存储库的持续集成 (CI) 的流行产品。今天,我们宣布了Dart团队的正式设置飞镖行动。此操作支持下载、安装和配置 Dart SDK,因此您可以在 GitHub 操作上轻松运行 Dart 生成和测试作业。

如果你为 pub.dev 创作 Dart 包,我们建议你为存储库启用使用 Github 操作的 CI 测试,为你(和包用户)提供有关包是否正常的信号。GitHub 操作上的 CI 作业对公共存储库免费

img

设置飞镖简介

如果你有一个包含 Dart 应用程序的 GitHub 存储库,则只需单击几下即可使用 GitHub 操作和 setup-dart 操作启用 CI 测试。在这里,我们有一个名为 myapp 的新 GitHub 存储库,其中包含通过运行
使用 Dart 工具生成的小型应用程序的起点。dart create --template console-full myapp

接下来,打开 GitHub Web UI,然后单击“操作”选项卡:

img

在介绍的正下方,您应该会看到一个部分,建议 Dart 存储库的工作流程:

img

单击“设置此工作流”按钮,你将转到 GitHub UI 以添加新文件。这是一个 YAML 文件,用于定义要在存储库中运行的 GitHub 操作工作流。让我们回顾一下模板工作流文件建议的每个组件。.github/workflow/dart.yml

首先,我们定义工作流的名称,该名称将显示在操作管理 UI 中:

name: Dart

接下来,我们定义何时运行工作流(触发工作流的事件)。在这里,流配置为在推送到主分支或主分支的 PR 时运行。我个人发现,当我在运行工作流时遇到问题时,通常是因为我拼错了分支名称。

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

然后是作业列表,每个作业都有一个名称(此处)。每个作业都有自己的定义,包括运行作业的位置列表(此作业在 Ubuntu Linux 上运行)以及要执行的步骤:test

jobs:
  test:
    runs-on: ubuntu-latest
    steps:

至于具体的测试,首先我们检查下的文件库,然后运行新的 setup-dart 操作。这将下载并安装 Dart SDK,然后将 CLI 和 pub 全局目录添加到路径中。此处我们不指定要安装的 Dart SDK,因此该操作将安装最新的稳定通道 SDK。test``dart

      - uses: actions/checkout@v2
      - uses: dart-lang/setup-dart@v1

然后,我们可以继续执行所需的测试,例如格式化,分析和单元测试:

      - name: Install dependencies
        run: dart pub get      - name: Verify formatting
        run: dart format — output=none — set-exit-if-changed .      - name: Analyze project source
        run: dart analyze      - name: Run tests
        run: dart test

有关完整示例,请参阅我们的 package:characters 工作流程

指定开发工具包版本

安装飞镖操作支持指定要安装的飞镖版本。这可以采用以下两种形式之一:

  • 特定版本,例如 或2.9.0``2.12.0–259.12.beta
  • 发布渠道的最新版本,例如 或stable``beta

要指定版本,请使用参数,可以直接或作为测试矩阵的一部分:sdk

matrix:
    os: [ubuntu-latest, macos-latest, windows-latest]
    sdk: [2.10.0, stable, beta]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v2
      - uses: dart-lang/setup-dart@v1.0
        with:
          sdk: ${{ matrix.sdk }}

此矩阵的结果是九个单独运行的作业:

img

现在一切都已过去,您可能希望向文件添加状态徽章以显示测试状态。README.md

替代解决方案

GitHub Actions 是几种流行的持续集成解决方案之一。其他支持Dart SDK的公司包括TravisAppVeyorCodeShip。对于 Flutter 应用程序的测试,选项包括来自 Nevercode 的 CodemagicCirrus CIBitrise。GitHub Actions for Flutter 应用程序由社区贡献的操作启用,例如 Flutter-action

现在就是这样。我们希望您喜欢 Dart 的这种新的 CI 支持,如果您对 setup-dart 有任何反馈或问题,请在问题跟踪器中告诉我们。

宣布飞镖 2.12

声音零安全和飞镖FFI运送到稳定通道。

今天我们宣布推出 Dart 2.12,具有稳定版本的声音零安全和 Dart FFI。空安全是我们最新的主要生产力功能,旨在帮助您避免空错误,这是一类通常难以发现的错误,如本视频介绍中所述。FFI 是一种互操作性机制,允许您调用用 C 编程语言编写的现有代码,例如调用 Windows Win32 API。Dart 2.12 现已上市。

img

Dart平台的独特功能

在我们详细了解声音零安全和FFI之前,让我们讨论一下它们如何适应Dart平台的目标。编程语言往往共享很多功能。例如,许多语言支持面向对象的编程或在 Web 上运行。真正使语言与众不同的是它们独特的功能组合。

img

Dart的独特功能跨越三个维度:

  • 可移植性:高效的编译器为设备生成 x86 和 ARM 机器代码,并为 Web 生成优化的 JavaScript。支持广泛的目标 – 移动设备、台式电脑、应用后端等。一组广泛的库和包提供了适用于所有平台的一致 API,从而进一步降低了创建真正的多平台应用的成本。
  • 高效:Dart 平台支持热重载,支持本机设备和 Web 的快速迭代开发。Dart 提供了丰富的构造,如隔离和异步/等待,用于处理常见的并发和事件驱动的应用模式。
  • 稳健:Dart 的声音、零安全类型系统可在开发过程中捕获错误。整个平台具有高度的可扩展性和可靠性,十多年来,各种应用程序都在生产中使用,包括Google Ads和Google Assistant等关键业务应用程序。

声音零安全使类型系统更加坚固,并可实现更好的性能。Dart FFI 允许您使用现有的 C 库以获得更好的可移植性,并为您提供使用高度优化的 C 代码执行性能关键型任务的选项。

声音零安全

声音零安全是自 Dart 2.0 中引入声音类型系统以来对 Dart 语言的最大补充。空安全进一步加强了类型系统,使你能够捕获空错误,这是应用崩溃的常见原因。通过选择空安全,您可以在开发过程中捕获空错误,从而防止生产崩溃。

声音零安全是围绕几个核心原则设计的。让我们重新审视一下这些原则如何影响作为开发人员的您。

默认情况下不可为空:对类型系统的根本更改

空安全之前的核心挑战是,您无法区分预期传递 null 的代码和不适用于空的代码。几个月前,我们在 Flutter 主通道中发现了一个错误,其中各种颤振工具命令在某些机器配置上会崩溃并显示空错误:。根本问题是这样的代码:The method '>=' was called on null

final int major = version?.major;
final int minor = version?.minor;
if (globals.platform.isMacOS) {
  // plugin path of Android Studio changed after version 4.1.
  if (major >= 4 && minor >= 1) {
  ...

你能发现错误吗?因为可以为空,所以两者都可以是空的。这个错误似乎很容易单独发现,但在实践中,这样的代码总是溜走,即使有像 Flutter 存储库中使用的严格的代码审查过程。在零安全的情况下,静态分析会立即捕获此问题。(在DartPad中现场尝试version``major``minor

img

IDE 中分析输出的屏幕截图

这是一个非常简单的错误。在 Google 内部代码中使用空安全的过程中,我们看到发现了更复杂的错误。其中一些是多年来已知的错误,但如果没有来自 null Safety 的额外静态检查,团队就无法找到原因。以下是一些示例:

  • 一个内部团队发现,他们经常检查永远不会为空的表达式的空值。此问题最常见于使用 protobuf 的代码中,其中可选字段在未设置时返回默认值,并且永远不会返回 null。因此,代码错误地检查了默认值,混淆了默认值和 null 值。
  • Google Pay 团队在他们的 Flutter 代码中发现了一些错误,当尝试在上下文之外访问 Flutter 对象时,它们会失败。在 null 安全之前,这些对象将返回 null 并屏蔽错误;对于 null 安全性,声音分析确定这些属性永远不会为空,并抛出分析错误。State``Widget
  • Flutter 团队发现了一个错误,如果传递给 中的参数,Flutter 引擎可能会崩溃。在 null 安全迁移期间,他们添加了一个提示,将 Scene 标记为不可空,然后能够轻松防止 null 可能触发的潜在应用崩溃。null``scene``Window.render()

默认情况下使用不可为空

启用 null 安全后,变量声明的基础知识将更改,因为默认类型不可为 null:

// In null-safe Dart, none of these can ever be null.
var i = 42; // Inferred to be an int.
String name = getFileName();
final b = Foo();

如果要创建可以包含值或 null 的变量,则需要通过在类型中添加后缀来在变量声明中明确说明这一点:?

// aNullableInt can hold either an integer or null.
int? aNullableInt = null;

空安全的实现是可靠的,丰富的静态流分析使使用可为空的类型变得更加容易。例如,在检查 null 后,Dart 会将局部变量的类型从可为 null 提升为不可为空:

int definitelyInt(int? aNullableInt) {
  if (aNullableInt == null) {
    return 0;
  }
  // aNullableInt has now promoted to a non-null int.
  return aNullableInt; 
}

我们还添加了一个新关键字 。当命名参数被标记为(这在 Flutter widget API 中经常发生)并且调用者忘记提供参数时,就会发生分析错误:required``required

img

增量迁移到空安全

因为空安全是对我们打字系统的根本性改变,如果我们坚持强制采用,那将是极具破坏性的。因此,您可以决定何时合适,空安全是一项选择加入功能:您可以使用 Dart 2.12,而无需强制启用空安全。你甚至可以依赖已启用 null 安全的包,无论应用或程序包是否启用了 null 安全性。

为了帮助您将现有代码迁移到 null 安全性,我们提供了迁移工具和迁移指南。该工具首先分析所有现有代码。然后,您可以交互式地查看工具推断的可为空性属性。如果您不同意该工具的任何结论,可以添加可空性提示来更改推论。添加一些迁移提示可能会对迁移质量产生巨大影响。

img

目前,使用和不启用声音零安全创建的新包和应用。我们希望在未来的稳定版本中改变这一点,当我们看到大部分生态系统已经迁移时。您可以使用 在新创建的包或应用程序中轻松启用空安全dart create``flutter create``dart migrate

Dart生态系统的零安全迁移现状

在过去的一年里,我们提供了几个声音零安全的预览版和测试版,目标是用支持零安全的软件包为生态系统播种。此准备工作非常重要,因为我们建议按顺序迁移到声音 null 安全性 – 不应在包或应用的所有依赖项迁移之前迁移包或应用。

我们已经发布了由DartFlutterFirebaseMaterial团队提供的数百个软件包的null安全版本。我们已经看到了令人惊叹的Dart和Flutter生态系统的大力支持,因此 pub.dev 现在有超过一千个支持零安全的软件包。重要的是,最受欢迎的软件包已经首先迁移,因此前 100 个最受欢迎的软件包中有 98%,前 250 个软件包中有 78% 和前 500 个软件包中有 57% 已经支持空安全,以便今天的发布。我们期待在未来几周内看到更多具有空安全性的包裹 pub.dev。我们的分析表明,pub.dev 上的绝大多数软件包已经畅通无阻,可以开始迁移

完全健全的零安全的好处

完全迁移后,Dart 的空安全性是合理的。这意味着 Dart 可以 100% 确定具有不可为空类型的表达式不能为空。当 Dart 分析您的代码并确定某个变量不可为空时,该变量始终不可为空。Dart 与 Swift 共享声音零安全性,但其他编程语言并不多。

Dart的零安全性的合理性还有另一个受欢迎的含义:这意味着你的程序可以更小更快。因为 Dart 确定不可为空的变量永远不会为空,所以 Dart 可以优化。例如,Dart 提前 (AOT) 编译器可以生成更小、更快的本机代码,因为它在知道变量不为 null 时不需要添加对 null 的检查。

Dart FFI 用于将 Dart 与 C 库集成

Dart FFI 使您能够利用 C 库中的现有代码,从而提高可移植性,并与高度调优的 C 代码集成,以执行性能关键型任务。从Dart 2.12开始,Dart FFI已经退出测试阶段,现在被认为是稳定的,可以投入生产。我们还添加了一些新功能,包括嵌套结构和按值传递结构。

按值传递结构

结构可以通过引用和 C 代码中的值传递。FFI 以前仅支持按引用传递,但从 Dart 2.12 开始,您可以按值传递结构。下面是两个通过引用和值传递的 C 函数的小示例:

struct Link {
  double value;
  Link* next;
};void MoveByReference(Link* link) {
  link->value = link->value + 10.0;
}Coord MoveByValue(Link link) {
  link.value = link.value + 10.0;
  return link;
}

嵌套结构

C API 通常使用嵌套结构,即本身包含结构的结构,例如以下示例:

struct Wheel {
  int spokes;
};struct Bike {
  struct Wheel front;
  struct Wheel rear;
  int buildYear;
};

从 Dart 2.12 开始,FFI 支持嵌套结构。

接口更改

作为声明 FFI 稳定的一部分,为了支持上述功能,我们进行了一些较小的 API 更改。

现在不允许创建空结构(中断性变更 #44622),并生成弃用警告。可以使用新类型 来表示空结构。函数 、 和现在需要编译时类型参数(重大更改 #44621)。由于添加了新的便利函数,因此对于常见情况,不需要额外的分配和释放内存样板:Opaque``dart:ffi``sizeOf``elementAt``ref``package:ffi

// Allocate a pointer to an Utf8 array, fill it from a Dart string,
// pass it to a C function, convert the result, and free the arg.
//
// Before API change:
final pointer = allocate<Int8>(count: 10);
free(pointer);
final arg = Utf8.toUtf8('Michael');
var result = helloWorldInC(arg);
print(Utf8.fromUtf8(result);
free(arg);// After API change:
final pointer = calloc<Int8>(10);
calloc.free(pointer);
final arg = 'Michael'.toNativeUtf8();
var result = helloWorldInC(arg);
print(result.toDartString);
calloc.free(arg);

自动生成 FFI 绑定

对于大型 API 图面,编写与 C 代码集成的 Dart 绑定可能非常耗时。为了减轻这种负担,我们构建了一个绑定生成器,用于从 C 头文件自动创建 FFI 包装器。我们邀请您尝试一下:。package:ffigen

FFI 路线图

随着核心 FFI 平台的完成,我们将重点转向扩展 FFI 功能集,使其具有在核心平台之上分层的功能。我们正在调查的一些功能包括:

  • 特定于 ABI 的数据类型,如整数、整型size_t (#36140)
  • 结构中的内联数组 (#35763)
  • 包装结构 (#38158)
  • 联合类型 (#38491)
  • 向 Dart 公开终结器(#35770;但请注意,您已经可以使用 C 中的终结器。)

FFI 的用途示例

我们已经看到Dart FFI的许多创造性用途与一系列基于C的API集成。以下是一些示例:

  • open_file 是用于跨多个平台打开文件的单个 API。它使用 FFI 在 Windows、macOS 和 Linux 上调用本机操作系统 API。
  • win32 包装了最常见的 Win32 API,因此可以直接从 Dart 调用各种 Windows API。
  • objectbox 是一个由基于 C 的实现支持的快速数据库。
  • tflite_flutter使用 FFI 来包装 TensorFlow Lite API。

Dart语言的下一步是什么?

声音零安全是我们几年来对Dart语言所做的最大更改。接下来,我们将研究在坚实的基础上对语言和平台进行更多的增量更改。以下是我们在语言设计漏斗中尝试的一些内容的快速视图:

类型别名 (#65):为非函数类型创建类型别名的功能。例如,您可以创建一个 typedef 并将其用作变量类型:

typedef IntList = List<int>;
IntList il = [1,2,3];

三移运算符#120):添加一个新的、完全可重写的运算符,用于对整数执行无符号位移位。>>>

通用元数据批注 (#1297):扩展元数据批注以也支持包含类型参数的批注。

静态元编程 (#1482):支持静态元编程 — Dart 程序在编译过程中生成新的 Dart 源代码,类似于 Rust 和 Swift 函数构建器。此功能仍处于早期探索阶段,但我们认为它可能会支持当今依赖代码生成的用例。

Dart 2.12 现已上市

Dart 2.12具有声音零安全和稳定的FFI,现已在Dart 2.12Flutter 2.0 SDK中提供。请花点时间查看 DartFlutter 的已知空安全问题。如果您发现任何其他问题,请在 Dart 问题跟踪器中报告。

如果您开发了在 pub.dev 上发布的软件包,请立即查看迁移指南,并了解如何迁移到声音空安全。迁移包可能有助于取消阻止依赖于它的其他包和应用。我们还要非常感谢那些已经迁移的人!

我们很想听听您在声音零安全和 FFI 方面的经验。在下面发表评论或@dart_lang发推文给我们。

宣布飞镖 2.10

适用于所有 核心任务的全新统一工具。此外,还更新了空安全时间表和迁移原则。*dart*

由:

迈克尔·汤姆森

&

凯文·摩尔

今天,我们宣布了 Dart 的新版本,版本 2.10(两个点十)。此版本具有一个新的统一 Dart 开发人员工具:一个满足所有开发人员需求的单一工具,例如创建项目、分析和格式化代码、运行测试和编译应用程序。我们还更新了空安全路线图和时间表,并讨论了将现有代码迁移到空安全的原则。

img

全新的统一 Dart 开发人员工具

Dart 构成了 Flutter SDK 的基础:它不仅为 Flutter 应用程序提供支持的语言和运行时,而且还支持许多核心开发人员任务,如格式化、分析和测试代码。但是,虽然 Flutter 有一个通用的开发人员工具(命令),但 Dart 历史上有许多较小的开发人员工具(例如,和)。Dart 2.10 有一个新的、统一的开发人员工具,与该工具非常相似。此新工具支持所有常见任务,例如创建新项目和包;分析和格式化代码;以及运行、编译和测试项目。要使用该工具,只需运行以下命令:flutter``dartfmt``dartanalyzer``dart``flutter``dart

img

通过运行飞镖帮助了解 2.10 飞镖工具。

Flutter 在 Flutter SDK 中包含这个新的 Dart 工具。从今天的 Flutter 1.22 SDK 开始,目录(您可能在 中)包含 和 命令。如果您同时进行 Flutter 和通用 Dart 开发,则可以从单个 Flutter SDK 获得两种开发人员体验,而无需安装任何其他内容。/bin``PATH``flutter``dart

注意: 如果要下载并安装第二个 Dart SDK(可能是因为您需要不同的版本),请确保要默认使用的工具的 SDK 位于环境变量的开头。dart``PATH

在即将到来的稳定版本中,我们计划向此工具添加更多内容,并逐渐弃用较小的工具(、、等)。明年,我们预计将发布仅包含单个工具的Dart SDK。我们建议您在现在运行 Dart 命令时切换到新工具,无论是在终端中还是在持续集成 (CI) 脚本中手动运行,如果缺少任何内容或未按预期工作,请向我们提供反馈dart``dartdoc``dartfmt``dartanalyzer``dart

期待零安全

自从几个月前我们推出第一个技术预览版以来,我们对空安全产生了浓厚的兴趣。我们都期待零安全作为避免难以发现的空错误的工具,以及我们期望看到的声音零安全的性能改进的额外好处。如果您想了解更多信息,我们推荐我们新的了解空安全页面。如果您更喜欢短视频,请查看几个月前 Flutter Day 活动中空安全视频

何时可以使用空安全?以下是当前时间表:

  1. 使用技术预览版 2\ 进行 Flutter 实验:我们已经成功迁移了 Flutter 的大部分内容。很快——可能在下个月内——我们希望迁移完整的 Flutter 框架,从而准备好在 Flutter 上进行实验性使用。您将能够在 Flutter 示例中尝试空安全性,并对 Flutter 应用程序和软件包进行试用迁移。需要传递试验标志,不应在生产中使用它,也不应发布任何迁移的包。
  2. 使用 beta\ 进行早期软件包迁移:今年晚些时候,我们将完成性能调整并有足够的测试覆盖率,让我们相信该功能按预期工作,并且向后兼容性是可靠的。届时,我们将发布该功能的测试版,您无需传递实验标志。我们希望看到软件包所有者开始将他们的软件包迁移到 null 安全性,并进行最后一轮验证该功能已准备好发布稳定版本。
  3. 稳定版的生产使用:根据测试版发布的反馈,我们将修复所有剩余问题,然后发布到稳定版。很难说出具体的时间表,但我们正在考虑明年初。一旦该功能稳定下来,我们希望看到大量采用空安全,将空安全应用程序发布到商店,并将许多空安全包发布到稳定版本中 pub.dev。

迁移到空安全的原则

我们想分享我们的空安全迁移指导原则。

准备就绪时采用

空安全是对Dart打字系统的根本性改变。它改变了变量声明的基础知识,因为我们决定默认情况下使变量不可为空:

Without null safety                 With null safetyString s; // A String or null.      String s; // A String, not null.

如果我们坚持强制收养,这种根本性的变化将是极具破坏性的。我们希望让您决定何时合适,因此空安全是一项选择加入功能:您将能够使用最新的 Dart 和 Flutter 版本,而无需在准备好之前强制启用空安全。甚至可以从尚未启用 null 安全的应用或包中依赖已启用 null 安全的包。

按顺序逐步采用

我们强烈建议按顺序迁移代码,首先迁移依赖项关系图的叶子。例如,如果 C 依赖于 B 而 B 依赖于 A,则首先将 A 迁移到空安全,然后迁移 B,然后迁移 C。无论 A、B 和 C 是库、包还是应用,此顺序都适用。

为什么订单很重要?尽管在迁移依赖项之前可以取得一些迁移代码的进展,但如果依赖项在迁移期间更改其 API,则可能需要执行第二次迁移传递。我们将提供工具来帮助你找出哪些依赖项已迁移。如果您是包作者,则为了避免破坏 API 的风险,请等到所有依赖项都迁移完毕后再发布 null 安全版本。

使用自动化工具降低迁移成本

当您的依赖项准备就绪并选择执行迁移时,您可以使用我们的迁移工具。该工具的工作原理是分析所有现有代码,查找哪些声明可以不可为空(保持不变),哪些声明必须为空(声明上需要可空性标记)。?

迁移工具是交互式的,因此您可以查看该工具推断的可为空性属性。如果您不同意该工具的任何结论,可以添加可空性提示来更改推论。例如,如果要使 API 不可为空,即使需要进行一些重构,也可以告诉该工具并重新运行迁移分析。添加一些迁移提示可能会对迁移质量产生巨大影响。

img

充分利用即可获得全部收益

迁移所有代码及其所依赖的包后,就可以以健全的 null 安全性执行代码。在此之前,您的代码将继续像现在一样运行和编译,但完全健全的 null 安全性可实现完整的运行时验证和编译器优化。使用声音空安全性运行测试有助于避免运行时空断言的问题,而使用声音空安全性编译应用程序可确保获得当前和未来的优化,例如更小的编译输出和更快的执行。

后续步骤

新的开发人员工具现已在Dart 2.10 SDK和Flutter 1.22 SDK中提供。如果你已经有一个 Flutter SDK,你可以通过一个命令简单地通过运行来获取一个 Dart SDK;这将给你Flutter 1.22 SDK,它嵌入了Dart 2.10。我们建议您立即切换到新工具,如果缺少任何内容或无法按预期工作,请向我们提供反馈dart``dart``flutter upgrade``dart

我们很快就会有更多关于空安全的新闻——很可能在下个月,届时我们预计 Flutter 团队的朋友将准备好一个支持空安全的 Flutter 框架进行实验。请关注 Flutter 博客以获取更新。同时,您可以使用具有空安全的 DartPad 试验空安全 Dart 代码,并通过阅读我们的空安全文档了解有关功能设计的更多信息。

宣布飞镖 2.8

更快的打包工具,确保依赖项永远不会过时的新工具

今天,我们宣布发布 Dart SDK 的新版本 2.8。我们继续看到Dart社区的惊人增长;我们现在有数以百万计的 Flutter 开发人员使用 Dart 作为他们的客户端优化语言,以便在任何平台上构建快速应用程序。虽然我们仍在努力完成即将推出的空安全功能,以使 Dart 成为用于构建快速稳定用户界面的更优化的语言,但我们有一些令人兴奋的新功能,专注于提高开发人员在管理依赖项时的工作效率。

Dart平台通过pub客户端工具和 pub.dev 包存储库内置了对包管理的支持,该存储库在过去一年中增长了200%,现在拥有近10,000个包。作为我们正在进行的改进 Dart 生态系统工作的一部分,Dart 2.8 SDK 为 pub 客户端工具带来了两项改进:在 中更好的性能,以及用于确保包依赖项保持最新的新工具。pub get

Dart 2.8 还对 Dart 语言和库进行了一系列小的突破性更改。这些更改为我们的第一个版本的空安全功能奠定了基础。

img

宣布 Dart 2.8:更快的打包工具,确保依赖项永不过时的新工具

中断性变更为空安全铺平道路

应用程序崩溃的常见来源是尝试使用恰好是 的变量的代码。Tony Hoare爵士于1965年在ALGOL编程语言中引入了空引用,他在2009年的QCon演讲中称其为“十亿美元的错误”。在某些情况下,空值很有用;挑战在于将这些与不是的情况分开。在过去的一年里,我们一直在忙于在Dart中建立对声音零安全性的支持。此支持将扩展类型系统以表达始终不可为 null 的变量,但除此之外,类型系统将是完全健全的:Dart 编译器和运行时将能够信任这些类型,并且能够在类型系统保证变量不为 null 时生成优化的代码。null

可以想象,这是一项艰巨的任务,有很多活动部件。为了确保我们能够使用干净的语义构建空安全,我们决定在 Dart 语言和库中进行一些小的突破性更改。这些重大更改对 Dart 类型系统的极端情况和一些 Dart 核心库进行了细微调整,以确保与 null 相关的出色可用性和性能。我们预计这些重大更改(在 Dart 公告列表中预先宣布)的实际影响对于常规应用代码的影响很小。如果您在使用 Dart 2.8 时遇到任何问题,我们建议您查看中断性更改及其说明和缓解步骤。如果这不能解决问题,请在我们的问题跟踪器中提交问题。要预览空安全体验,请尝试空安全游乐场

更高质量的包装生态系统

酒吧包管理器和 pub.dev 网站为 Dart 和 Flutter 不断增长的生态系统提供支持。pub.dev 有近 10,000 个软件包,我们不断对共享的许多有趣软件包感到惊讶。我们的核心任务是帮助包作者创建高质量的包并帮助应用开发人员找到这些包 – 例如,我们添加了改进的 pub.dev 发现经过验证的发布者和 Flutter 收藏夹

今天,我们宣布从 pub.dev 存储库检索包时的性能要快得多,并且有一个新工具可帮助您保持所有包依赖项的更新。由于新式应用的复杂性,你的应用可能依赖于数十个包。但是,如何将它们全部更新到最新版本,以确保获得最新的依赖项以及所有可用的错误修复和性能改进?从 Dart 2.8 开始,您可以使用 ,这是一个新工具,用于自动确定哪些依赖项需要更新到最新和最好的版本。pub outdated

Dart 2.8 酒吧工具性能改进

我们通过添加对运行时并行获取软件包的支持以及延迟预编译来优化 pub 工具的性能。pub get``pub run

在运行使用 创建的新项目的非正式基准测试中,总执行时间从 Flutter 1.12(使用 Dart 2.7)中的大约 6.5 秒减少到 Flutter 1.17 (Dart 2.8) 中的 2.5 秒。在像 Flutter 画廊这样的大型应用程序中,时间从大约 15 秒下降到大约 3 秒!flutter pub get``flutter create

使用 管理依赖项pub outdated

img

Dart 代码中的依赖项在 pubspec 文件中捕获。当您通过运行命令从 pub.dev 检索包时,发布版本求解器(使用 PubGrub 算法)将运行一个过程来确定满足 pubspec 中列出的约束的所有依赖项的最新可能版本集。请注意,pub 使用单版本方案,其中每个包都包含在应用中的单版本中;这是一项重要的优化,可确保应用大小尽可能小。pub get

最佳做法是始终使用最新的稳定包版本,但这样做可能很费力。Dart 支持升级到语义兼容的最新版本,但如果不更新 pubspec,则无法包含包的新主要版本。该命令通过将当前使用的版本与 pub.dev 上可用的最新版本进行比较,帮助您了解次要版本和主要版本何时可用。pub upgrade``pub outdated

让我们考虑一个具体的例子。假设您正在构建一个应用程序,它包含以下内容:pubspec.yaml

dependencies:
  foo: ^1.3.0
  bar: ^2.0.0

运行 ,该工具将创建具有以下版本的文件:pub get``pubspec.lock

packages:
  foo:
    version: "1.3.0"
  bar:
    version: "2.0.1"

几个月过去了,pub.dev 现在有了新版本的(1.3.1)和(2.1.0和3.0.3)。您如何发现这些新版本可用?对于次要版本升级(1.4.0 和 2.1.0),您可以运行 pub 升级,但这不会为您提供 3.0.0。要发现新版本,您必须访问 pub.dev 上的每个软件包并查看其最新版本。或者,您可以使用社区解决方案,例如Paulina Szklarska的版本检查器或Jeroen Meijer的pubspec助手。foo``bar``foo``bar``bar

有了 ,Dart SDK 现在支持版本发现。如果您使用的是支持 Dart 或 Flutter 的 IDE,请使用打开文件时显示的 Pub 过时操作。或者您可以从终端运行(或):pub outdated``pubspec.yaml``pub outdated``flutter pub outdated

$ pub outdatedDependencies            Current  Upgradable  Resolvable  Latest
foo                     1.3.0    1.3.1       1.3.1       1.3.1
bar                     2.0.1    2.1.0       3.0.3       3.0.31 upgradable dependency is locked (in pubspec.lock) to an older version.To update it, use `pub upgrade`.1 dependency is constrained to a version that is older than a resolvable version.

此输出告诉我们,我们可以通过以下方式自动升级到 1.3.1 ,这将使我们进入可用的最新版本。但它也告诉我们,虽然我们可以自动升级到 2.1.0,但版本 3.0.3 可用。由于升级到 3.0.3 是主要版本升级,因此我们需要通过编辑文件来选择加入该升级:foo``pub upgrade``foo``bar``bar``pubspec.yaml

dependencies:
  foo: ^1.3.0
  bar: ^3.0.3

在我们进行编辑并运行后,现在报告所有依赖项都是最新的:pub upgrade``pub outdated

$ pub outdatedDependencies            Current   Upgradable  Resolvable  Latestall up-to-date

成功,我们是最新的!由于我们刚刚选取了新版本(包括新的主要版本),因此应查看这些版本中的任何潜在中断性更改,并运行所有测试以确保我们的应用仍按预期工作。

后续步骤

性能改进、重大更改和新命令现已在稳定的 Dart 2.8 SDK 和稳定的 Flutter 1.17 SDK 中提供。建议立即运行以查看依赖项的运行状况!pub outdated``pub outdated

如果您发现任何问题,请在发布会问题跟踪器中报告,或者在 SDK 问题跟踪器中报告这些问题以了解一般问题。我们很想听听您对 .在下面发表评论或向@dart_lang发送推文。pub outdated

宣布飞镖 2.7:更安全、更具表现力的飞镖

今天,我们宣布 Dart 2.7 SDK 的稳定版本,并为开发人员提供了额外的新功能。对于 Dart 来说,这是忙碌的一年,这是我们针对任何平台上的快速应用程序进行客户端优化的语言。我们已经发布了六个新版本,其中包含数十个新功能。看到 Dart 社区使用这些功能是非常有益的,我们很高兴最近的 GitHub Octoverse 报告将 Dart 列为 #1 增长最快的语言,按贡献者数量排名。

Dart 2.7 添加了对扩展方法的支持,以及用于处理具有特殊字符的字符串的新包。我们更新了空安全(类型安全的可为空和不可为空的类型)和 DartPad 中全新的空安全游乐场体验。在生态系统级别,pub.dev 具有新的“赞”功能,用于向您欣赏的包提供反馈。Dart 2.7 今天可从 dart.dev 下载 SDK,并且它也内置在今天的 Flutter 1.12 版本中

img

扩展方法

Dart 2.7 添加了一个请求已久的强大新语言功能:扩展方法。这些使你能够向任何类型(甚至是你无法控制的类型)添加新功能,并具有常规方法调用的简洁和自动完成体验。

让我们看一个小示例:添加对从 String 解析整数和双精度的支持。作为应用程序开发人员,我们不能更改类,因为它是在 dart:core 库中定义的,但是通过扩展方法我们可以扩展它!定义此扩展后,我们可以在 String 上调用我们的新方法,就好像该方法是在 String 类本身上定义的一样:String``parseInt

extension ParseNumbers on String {
  int parseInt() {
    return int.parse(this);
  }  double parseDouble() {
    return double.parse(this);
  }
}main() {
  int i = '42'.parseInt();
  print(i);
}

扩展方法是静态的

扩展方法是静态解析和调度的,这意味着您无法对类型为 .此处调用在运行时引发异常:dynamic

dynamic d = '2';d.parseInt();→ Runtime exception: NoSuchMethodError

扩展方法与 Dart 的类型推断配合得很好,因此在下面的变量中推断出具有 type ,并且 String 上的扩展可用:v``String

var v = '1';
v.parseInt(); // Works!

由于扩展方法是静态解析的,因此它们与调用静态函数或帮助程序方法一样快,但调用语法要友好得多。

扩展可以具有类型变量

想象一下,我们要定义一个扩展,用于获取偶数索引处的元素。我们希望此扩展适用于任何类型的列表,返回与输入列表类型相同的新列表。我们可以通过使扩展泛型并将其类型参数应用于它扩展的类型和扩展方法来做到这一点:List

extension FancyList<T> on List<T> {
  List<T> get evenElements {
    return <T>[for (int i = 0; i < this.length; i += 2) this[i]];
  }
}

扩展方法实际上是扩展成员

我们调用功能扩展方法,因为如果您在其他编程语言中使用了相应的语言功能,这是熟悉的术语。但在 Dart 中,该功能更通用:它还支持使用新的 getter、setter 和运算符扩展类。在上面的 FancyList 示例中,是一个 getter。下面是为移动字符串添加运算符的示例:evenElements

extension ShiftString on String {
  String operator <<(int shift) {
    return this.substring(shift, this.length) + this.substring(0, shift);
  }
}

来自社区的优秀示例

我们已经看到Dart社区中的许多开发人员尝试使用扩展方法。以下是我们迄今为止看到的一些很酷的用途。

Jeremiah Ogbomo 创建了 time 包,它使用 on(整数和双精度的基类)的扩展来轻松构造对象:num``Duration

// Create a Duration via a `minutes` extension on num.
Duration tenMinutes = 10.minutes;// Create a Duration via an `hours` extension on num.
Duration oneHourThirtyMinutes = 1.5.hours;// Create a DateTime using a `+` operator extension on DateTime.
final DateTime afterTenMinutes = DateTime.now() + 10.minutes;

Marcelo Glasberg 创建了一个 i18n(国际化)包,该包使用扩展方法来简化字符串本地化:

Text('Hello'.i18n) // Displays Hello in English, Hola in Spanish, etc.

Simon Leier创建了dartx包,其中包含一系列核心Dart类型的扩展。一些例子:

var allButFirstAndLast = list.slice(1, -2);    // [1, 2, 3, 4]
var notBlank = ' .'.isBlank;                   // false
var file = File('some/path/testFile.dart');
print(file.name);                              // testFile.dart
print(file.nameWithoutExtension);              // testFile

Brian Egan正在使用扩展方法更新流行的RxDart包,以重新定义用于处理流的API。

安全子字符串处理

Dart 的标准字符串类使用 UTF-16 编码。这是编程语言中的常见选择,尤其是那些支持在设备和 Web 上本机运行的语言。

UTF-16 字符串通常工作得很好,并且编码对开发人员是透明的。但是,在操作字符串时,尤其是在操作用户输入的字符串时,用户感知的字符与以 UTF-16 编码为代码单元的内容之间可能会遇到差异。让我们看一个小例子,提取用户输入的字符串的前三个字符:

var input = ['Resume'];
input.forEach((s) => print(s.substring(0, 3)));$ dart main.dart
Res

到目前为止没有问题;我们在输入列表中打印了字符串的前三个字符,结果是 .现在让我们考虑来自不同地区的用户,他们可能会输入包含重音、韩文(韩语脚本)甚至表情符号组合的字符串来表示“简历”的概念:Res

// New longer input list:
var input = ['Resume', 'Résumé', '이력서', '💼📃', 'Currículo'];$ dart main.dart
Res
Ré
이력서
💼�
Cur

嗯,其中一些有效,但是元素和发生了什么?对于,为什么我们得到一个“两个字符”的字符串?对于,奇怪的问号是怎么回事?这里的问题在于Unicode的黑暗角落。重音实际上是两个码位:e组合尖音。而且📃,带有卷曲表情符号的页面是一个单一的代码点,恰好用一对代理项编码。困惑?Résumé``💼📃``Résumé``💼📃``é``Résumé``U+d83d U+dcc3

正如我们所说,通常您无需担心字符和代码点。如果您所做的只是接收、传递和移交整个字符串,则内部编码是透明的。但是,如果您需要迭代字符串的字符或操作字符串的内容,则可能会遇到麻烦。好消息是Dart 2.7引入了一个新的包字符,来处理这些情况。此包支持被视为用户感知字符序列的字符串,也称为 Unicode 字素簇。使用字符包,我们可以通过对缩短文本的代码进行小的更改来修复我们的代码:

// Before:
input.forEach((s) => print(s.substring(0, 3)));// After, using the characters package:
input.forEach((s) => print(s.characters.take(3)));

首先,我们从字符串创建一个新实例(使用方便的扩展方法)。然后我们使用漂亮的方法来提取最初的 3 个字符。Characters``s``.characters``take()

此新软件包的技术预览版可在 pub.dev 上获得。我们很想听听您对这个套餐的想法。如果您发现任何问题,请报告。

空安全预览

几个月前,我们宣布打算在 Dart 中支持 null 安全,增加了对安全访问对象引用的支持,而不会触发 null 引用异常。今天,我们为您提供了一种预览空安全静态分析的方法。让我们看一个小的激励例子:

void main() {
  Person('Larry', birthday: DateTime(1973, 03, 26)).describe();
  Person('Sergey').describe();
}class Person {
  String firstName;
  DateTime birthday;
  Person(this.firstName, {this.birthday});  void describe() {
    print(firstName);
    int birthyear = birthday?.year;
    print('Born ${DateTime.now().year - birthyear} years ago');
  }
}

如果我们运行此代码,它在描述第二个人时会崩溃并出现空指针异常,因为该人没有生日设置。我们犯了一个编码错误:虽然我们确实通过在构造函数中使字段可选并通过测试空生日来预测一些人的生日未知,但我们忘记处理 null 的情况。birthday``birthday?.year``birthyear

让我们尝试将此代码粘贴到我们新的空安全操场中,这是 DartPad 的一个特殊版本,其中包含空安全功能的静态分析部分的技术预览。甚至不运行代码,我们可以看到三个问题:

img

具有空点安全性的 DartPad 显示与空点相关的三个分析错误

通过修复这些分析错误,我们可以开始利用零安全性。尝试在空安全操场中进行以下编辑(最终获得此安全代码):

  1. 若要声明生日可能为 null,请更改为
    *DateTime birthday*``*DateTime? birthday*
  2. 若要在生日为空时声明出生年份可能为空,请更改为
    *int birthyear*``*int? birthyear*
  3. 将最后一个打印调用包装在空测试中:
    *if (birthyear != null)* {…}

我们希望这个例子能很好地表明我们想要的空安全体验。如前所述,这个游乐场只是部分零安全的早期技术预览,因为它正在建造中。我们正在努力完成 Dart SDK 中空安全性的第一个测试版。以下是我们正在为 Beta 版所做的工作:

  1. 完成可为空和不可为空的引用的完整实现
  2. 将空安全集成到 Dart 的类型推断和智能提升中(例如,允许在赋值或空检查后安全访问可为空的变量)
  3. 移植 Dart 核心库以声明哪些类型可为空,哪些类型不可为空
  4. 添加迁移工具,该工具可以自动执行移植 Dart 应用和程序包的大多数升级任务

完成此工作后,我们将在测试版 SDK 中提供此功能,你可以开始在应用和程序包中利用该功能。我们还计划在实现新功能时不断更新 null 安全游乐场。

虽然我们确信许多开发人员希望在 null 安全可用后立即使用它,但您可以在方便时进行迁移,并在准备就绪时选择启用该功能。尚未选择加入该功能的库和包将能够依赖于已选择加入的库,反之亦然。

在接下来的几个月里,我们将有更多关于零安全的内容,包括有关如何为过渡做准备的更详细的建议。

👍 喜欢 pub.dev 上的包裹

今天在 pub.dev 上还推出了一项新的“喜欢”\功能。这引入了一个新的“人工信号”,用于指示您喜欢哪些包裹。要喜欢包裹,只需单击包裹详细信息旁边的竖起大拇指图标:

img

pub.dev 包详细信息页面,其中包含新的“赞功能”投票按钮

目前,我们不会将赞数计入整体评分模型,但我们计划在以后的版本中这样做。我们还计划对常规搜索 UI 和列表页面进行视觉大修,以突出包的相似功能。

谢谢

我谨代表 Dart 团队,感谢您以及 Dart 社区中的每个人一直以来的支持!请继续向我们提供反馈,并参与Dart讨论和社区。如果没有Dart社区的支持,我们就不会成为一个运作良好的开源项目。

对于Dart来说,2019年是令人难以置信的激动人心的一年,但我们并没有止步于此。我们对2020年有大胆的计划,包括发布dart:ffinull safety等功能的稳定版本,并引入新功能。我们邀请您立即开始使用 Dart 2.7。它可以从 dart.dev,今天的Flutter 1.12版本和最近重新设计的DartPad中获得。

宣布推出 Dart 2.6 和编译 Dart 到独立的本机可执行文件dart2native:

Dart已经提供了一套广泛的编译器,用于为移动设备和Web构建生产优化的代码。这些灵活的编译器使我们的框架合作伙伴能够针对各种外形规格:Android 和 iOS 上的 Flutter 应用程序、Web 和桌面上的 Flutter 应用程序、Web 上的 AngularDart 应用程序以及嵌入式设备上的 Google Assistant。

今天我们宣布,这是我们现有编译器集的扩展,能够将Dart程序编译为包含提前编译的机器代码的独立可执行文件。使用 dart2native,您可以使用 Dart 在 macOS、Windows 或 Linux 上为命令行创建工具。此功能的公告图片是使用该功能本身实现的:-)**dart2native**

img

Dart Native 和 dart2native 编译器

Dart多年来一直支持AOT(提前)编译为本机机器代码,因此Dart Native是相当成熟的技术。但是,在过去,我们仅通过 Flutter 在 iOS 和 Android 移动设备上公开了此功能。

借助 ,我们将扩展原生编译支持,以支持运行 macOS、Windows 和 Linux 的传统桌面操作系统。由于使用 创建的可执行文件是独立的,因此它们可以在未安装 Dart SDK 的计算机上运行。而且由于它们是使用 Dart 的 AOT 编译器编译的,因此可执行文件只需几毫秒即可开始运行。与其他 Dart 编译器和运行时一样,在编译为本机代码时,Dart 中提供了同一组丰富且一致的核心库dart2native``dart2native

我们听说许多客户要求为桌面操作系统进行 AOT 编译 — 这是我们的问题跟踪器中评分第六高的问题 — 因此我们很高兴能够提供此功能。

如果您以前使用过 dart2aot,那么从 2.6 开始,您将使用 dart2native。它提供了dart2aot功能的超集。

使用 dart2native 构建命令行应用

编译器是为命令行构建和部署基于 Dart 的应用程序的绝佳选择。这些应用通常使用库,例如(基本 I/O)、(网络)和(参数分析)。让我们回顾一下将“hello, world”应用程序编译为可执行文件的基础知识:dart2native``dart:io``package:http``package:args

源代码:hello.dart

main() {
  print(‘Hello Dart developers’);
}

编译为可执行文件:hello.dart``hello

$ dart2native src/hello.dart -o hello
Generated: /Users/mit/hello

运行测量执行时间:hello

$ time ./hello
Hello Dart developersreal 0m0.049s
user 0m0.018s
sys 0m0.020s

请注意该命令如何在短短 49 毫秒的总时间内启动、打印到 stdout和退出!

我们已经看到一些Dart开发人员已经尝试了命令行工具:dart2native

  • 来自 ASS(一种流行的 CSS 扩展工具)团队的 Natalie 报告说,在将基于 Dart 的 SASS 实现切换到使用 dart2native 进行编译后,它现在在性能上与基于 C++ 的实现 LibSass 具有竞争力。
  • 来自Dart DevRel团队的Filip使用dart2native重新编译了他的链接检查工具,并在检查小型站点时看到了27倍的加速

通过 dart:ffi 与 C 代码的互操作性

本机应用通常需要从周围的操作系统访问本机功能。这些系统 API 通常在基于 C 的本机库中公开,Dart 通过我们的 C 互操作新机制支持与这些库的互操作性,我们在 Dart 2.5 中以预览版形式发布。编译器与 兼容,因此您可以创建和编译使用它的本机 Dart 应用程序。dart:ffi``dart2native``dart:ffi

一位团队成员最近用于创建用于控制台应用开发的库,该库具有获取窗口尺寸、读取和设置光标位置、管理颜色以及读取键和控制序列等功能。使用能力使 Dart 成为控制台应用的一种非常强大的语言。dart:ffi``dart_console``dart:ffi

kilo:一个7MB的代码编辑器,用不到500行的Dart代码编写

使用 Dart 核心库和dart_console库,我们可以创建非常有趣的控制台应用程序。dart_console包包括一个完整的 kilo 演示,一个用 ~500 行 Dart 代码编写的控制台文本编辑器。kilo这个名字来源于它的起源,这是一个大约1000行代码的C实现。dart:ffi``kilo.c

使用新的编译器,我们可以轻松地将其打包,最终得到一个7MB的独立代码编辑器。下面是编译编辑器的演示,然后使用编译的编辑器编辑自己的源代码以修复错误:dart2native

img

用 Dart 编写的 kilo 编辑器,并使用 dart2native 编辑它自己的源代码编译为可执行文件

使用 dart2native 构建服务

dart2native 编译器的另一个潜在用途是用于小型服务——例如,支持使用 Flutter 编写的前端应用程序的后端。近年来,使用在无服务器计算上运行的服务是一个不断增长的趋势。这些是完全托管的服务,可自动扩展,包括从零纵向扩展和缩减到零(未运行),从而有可能大大降低成本,因为它们仅在实际运行时计费。Google Cloud 通过 Cloud Run 提供无服务器计算。

对于无服务器后端,快速启动服务至关重要。传统上,基于 Dart 的服务使用我们的 JIT(实时)编译器运行,但基于 JIT 的执行在启动时具有高延迟,因为代码需要编译和预热才能开始执行。通过提前将服务的代码编译为本机代码,可以避免这种延迟并立即开始运行。此外,使用本机代码,您可以创建磁盘占用量小且自包含的 Dart 服务,从而大大减少运行 Dart 服务的容器的大小。Dart开发人员Paul Mundt最近记录了他使用dart2native编译器的经验;通过使用本机代码,他能够将 Docker 映像的大小从 220MB 减少到 20MB,从而将 Docker 映像的大小减少 91%!有关服务器端应用程序包的更多详细信息,请参阅我们的文档。

可用性

该编译器从版本 2.6 开始在 Dart SDK 中可用,从今天开始从 dart.dev/get-dart 年开始提供。安装 SDK 后,您应该会在 bin/ 目录和 .Dart.dev 有更多文档dart2native``PATH

如果你通过 Flutter 获取 Dart SDK,请注意,当前的 Flutter 构建具有不完整的 dart2native 支持。我们建议您从 dart.dev/get-dart 安装 Dart 2.6 SDK。

已知限制

编译器的此初始版本具有一些已知的限制,如下所示。您可以通过在我们的 GitHub 问题跟踪器中为问题添加“竖起大拇指”来让我们知道哪些问题对您很重要。dart2native

  • 不支持交叉编译(问题 28617):dart2native 编译器仅支持为其运行的操作系统创建机器代码。因此,如果要为这三者创建可执行文件,则需要在macOS,Windows和Linux上运行编译器三次。执行此操作的一种方法是使用支持所有三个操作系统的 CI(持续集成)提供程序。
  • 无签名支持(问题 39106):生成的可执行文件使用的格式与标准签名工具(如 和 )不兼容。codesign``signtool
  • 不支持 和(请参阅 Dart 核心库)。dart:mirrors``dart:developer

Dart 2.6 中的其他更改

Dart SDK 的 2.6 版还有一些其他变化。

我们在 Dart 2.5 中推出了 C 互操作的新机制的预览版。Dart 2.6 有新版本的 .这个新版本有许多重大的 API 更改,使我们的 API 更易于使用,提供更多的类型安全性,并提供对内存的方便访问。有关其他详细信息,请参阅 Dart 2.6 更新日志。随着这些更改进入测试版,我们预计 API 更改的频率将大大降低,并且总体稳定性预计会很高。请继续通过问题跟踪器向我们提供反馈。dart:ffi``dart:ffi``dart:ffi

Dart 2.6 还包含令人兴奋的新语言功能扩展方法的预览。我们还需要一些润色和工具工作来完成这个功能,但我们希望在下一个Dart SDK版本中正式推出它。然后,我们将对扩展方法进行更多讨论;现在,您可以了解该功能背后的设计注意事项

后续步骤

下载 Dart 2.6 SDK (dart.dev/get-dart),使用 dart2native 构建一些很酷的东西,然后告诉我们。如果您愿意分享详细信息,请在本文底部留下回复。我们很高兴看到您构建的内容!

宣布飞镖 2.5:超强开发

今天,我们宣布 Dart 2.5 SDK 的稳定版本,其中包括两个主要的新开发人员功能的技术预览:ML Complete(由机器学习 (ML) 提供支持的代码完成)和用于直接从 Dart 调用 C 代码的外部函数接口。Dart 2.5 还改进了对常量表达式的支持。dart:ffi

此版本是我们朝着为任何平台创建快速应用程序的最佳客户端优化语言的愿景迈出的又一步。ML Complete 是我们现有生产力工具套件的强大补充,如热重载可自定义的静态分析和 Dart DevTools。第二个预览功能 使你能够利用运行 Dart 代码的许多操作系统上的现有本机 API,以及用 C 编写的现有跨平台本机库。dart:ffi

说到我们创建最佳客户端优化语言的雄心壮志,很高兴看到上周新的IEEE Spectrum Top Programming Language 2019评级出来,现在包括Dart。Dart进入IEEE Spectrum编程语言评级为#16。在趋势下也是#10,在过滤到移动语言时是#6(在Java,C,C++,C#和Swift之后)。

img

预览版:ML 完成,按机器学习排名的代码完成度

类型化编程语言的核心优点之一是,在这些类型中捕获的其他信息使 IDE/编辑器能够在开发人员键入代码时提供补全功能,从而帮助他们。通过代码补全,开发人员既可以避免拼写错误,又可以通过键入预期符号的开头并从提供的补全中进行选择来探索 API。

随着 API 的增长,探索变得困难,因为可能的完成列表太长,无法按字母顺序浏览。在过去的一年里,我们一直在努力将机器学习应用于这个问题。简化地说,这是通过分析大量 GitHub 开源 Dart 代码,根据给定上下文训练可能出现的成员模型。这个模型 – 由TensorFlow Lite提供支持 – 然后可用于预测开发人员正在编辑的下一个可能的符号。我们将此新功能称为 ML Complete。下面是使用 Flutter 框架开发新小部件的示例:MyHome

img

使用 ML Complete 创建 Flutter 小部件的示例开发人员体验

让我们更深入地了解一下它是如何工作的。假设您正在编写一个小程序来计算当前时间的一天时间。使用 ML Complete,您可以在下面的左侧获得体验。首先,请注意它如何能够基于现在具有名称的变量提供完成。接下来,注意我们明天如何完成变量名称,最后是现在提供的第二个完成。在右侧的非 ML Complete 体验中,我们必须手动开始键入,变量名称没有完成,并且该方法在列表中更靠后。DateTime.now()``add(…)``DateTime``tomorrow``add(…)

img

imgML 完成(左)和不完全(右)的代码完成体验

如何试用 ML Complete

ML Complete 今天推出预览版。它直接内置在Dart分析器中,因此可以在所有支持Dart的编辑器中使用,包括Android Studio,IntelliJ和VS Code。有关如何选择加入此预览功能的详细信息,以及如何提供反馈和报告问题的详细信息,请参阅此 Wiki 页面

由于该功能仍处于预览阶段,因此当前 Flutter 和 Dart 稳定版本中的版本不包括我们期望在以后版本中具有的性能和润色工作。因此,我们建议您在预览此功能时暂时使用 Flutter 开发频道或 Dart 开发频道

预览:用于 Dart-C 互操作的外部函数接口dart:ffi

许多开发人员要求我们更好地支持从 Dart 调用 C 代码。一个非常明确的信号是 Flutter 问题跟踪器,其中 C 互操作是评分最高的开放功能请求,票数超过 600 👍 票。这些请求背后有许多有趣的用例,从调用 stdlib.hWin32 等低级平台 API,到利用现有的跨平台库和用 C 编写的实用程序,如 TensorFlow、Realm 和 SQLite。

目前,对直接从 Dart 调用 C 的支持仅限于使用本机扩展深度集成到 Dart VM 中。或者,Flutter 应用程序可以通过使用平台通道调用主机并从那里调用 C 来间接使用 C;这是一个不希望的双重间接。我们希望提供一种新的机制,它提供出色的性能,易于操作,并且可以在许多受支持的Dart平台和编译器上运行。

Dart-C 互操作支持两种主要方案:

  • 在主机操作系统 (OS) 上调用基于 C 的系统 API
  • 调用基于 C 的库,适用于单个操作系统或跨平台

调用基于 C 的操作系统 API

让我们具体看一下第一类。我们将调用 Linux 命令。此命令允许执行任何系统命令;你传递给它的参数本质上是传递给 shell/终端并在那里运行。下面是此命令的 C 标头:system

任何互操作机制的核心挑战都是处理两种语言之间的语义差异。对于 ,Dart 代码需要表示两件事:dart:ffi

  1. C 函数及其参数类型和返回类型
  2. 相应的 Dart 函数及其类型

我们通过定义两个类型定义来做到这一点:

接下来,我们需要加载库并查找我们要调用的函数。如何执行此操作取决于操作系统;在此示例中,我们使用的是 macOS。(我们有适用于macOS,Windows和Linux的完整示例

接下来,我们使用与特定操作系统相关的编码对字符串参数进行编码,调用函数,并再次释放参数内存:

此代码执行系统命令,导致系统默认浏览器打开 dart.dev:

img

通过 dart:ffi 执行系统命令以打开默认浏览器

调用基于 C 的框架和组件

的第二个核心用途是调用基于 C 的框架和组件。本文开头讨论的基于 ML 的代码完成就是一个具体的例子!它使用TensorFlow Lite,这是一个基于C的API。使用允许我们在需要提供代码完成的所有操作系统上运行 TensorFlow,并具有原生 TensorFlow 实现的高性能。如果你想看看Dart TensorFlow集成的代码,看看这个存储库dart:ffi``dart:ffi

我们还希望调用基于 C 的库的功能对 Flutter 应用程序非常有用。你可以想象调用原生库,如 RealmSQLite,我们认为对于为 Flutter 桌面启用插件很有价值。dart:ffi

包装 API 和代码生成

您可能已经注意到,在描述函数和查找其符号时,有一些编程开销。很多这样的样板代码都可以从 C 头文件生成。我们目前专注于提供底层原语,但很乐意与任何有兴趣开发生成器的人合作。

如何尝试飞镖:ffi

该库将于今天推出预览版。由于它仍处于预览状态,因此我们建议您使用 Flutter 频道或 Dart 开发频道,以便在所做的更改和改进时快速访问这些更改和改进。请注意,从现在到完成,API 可能会发生重大更改,因为我们添加了润色并扩大了对常见模式的支持。您可以详细了解我们目前对第一个版本的计划。以下是您应该了解的一些限制:dart:ffi

  • 该库不支持嵌套结构、内联数组、打包数据或依赖于平台的基元类型。
  • 缺乏指针操作的性能(但可以使用Pointer.asExternalTypedData来解决)。
  • 该库不支持终结器(当对象即将被垃圾回收时调用的回调)。

C 互操作文档和 API 参考文档记录了核心概念,并指出了可以查看的示例。如果您遇到任何问题或有疑问,我们邀请您在Dart FFI讨论组上发帖,或提交问题dart:ffi

改进的常量表达式

Dart 长期以来一直支持创建常量变量和值;它们保证是编译时常量,因此具有非常好的性能特征。在以前的版本中,常量表达式有点有限。从 Dart 2.5 开始,我们支持更多定义常量表达式的方法,包括使用强制转换的功能以及 Dart 2.3 中附带的新控制流和集合传播功能:

结语

接下来的几个季度,我们面临着令人兴奋的工作,扩展方法的工作正在进行中,强制引用不可为空,以及除此之外的语言的一些早期计划。我们还在研究改进的并发支持,例如在现代手机上更好地使用多核处理器的能力。

我们特别热衷于默认情况下不可为空。我们已经为此功能制定了一个非常雄心勃勃的计划,并且正在进行大量工作。一些较新的语言从一开始就设计了对不可为空的支持,而大多数在更高版本中添加不可为空支持的现有语言都采用了相当有限的方法,仅限于额外的静态分析。我们方法的一个主要区别是,我们的目标是提供完整的声音不可为空的支持。简要解释一下,这意味着我们对不可空性的理解将扩展到类型系统的核心,一旦我们的类型系统知道某些东西是不可空的,我们就可以完全信任该信息,并且我们的后端编译器可以自由地优化代码。这种健全性在提供一致的“无异常体验”以及代码大小和运行时性能方面都具有很大的优势。

每当我们改变语言时,我们总是意识到它给我们的生态系统带来的负担。因此,我们还投入了大量资金,为现有代码提供丰富的迁移工具。我们希望此工具能够抵消大部分迁移成本。我们还添加了一些专用的语言和工具功能,支持逐步迁移,并将努力获取我们自己的代码和共享代码 https://pub.dev 迁移。

我们期待在今年晚些时候分享更多新闻!

宣布推出 Dart 2.3:针对构建用户界面进行了优化

今天,我们宣布Dart 2.3 SDK的稳定版本,具有新的语言功能,可以改善您在开发用户界面时的编码体验,为开发Flutter UI提供新的工具支持,以及两个新网站:dart.dev&pub.dev

img

飞镖的势头

我们每年期待的开发者研究报告之一是StackOverflow开发者调查,它提供了一个关于开发者趋势和对不同技术的看法的综合数据集。今年的版本展示了Dart的受欢迎程度和知名度的增长,它首次进入最受欢迎的语言名单,并与其他流行语言(如JavaScript,C#和Go)并列,领先于C++,F#和R等。同时,我们在 Flutter 社区的好朋友在最喜爱的框架列表中排名第三。上个月Codementor关于学习和不学习哪些编程语言的调查也有类似的积极消息:

真正获得“最进步”称号的语言的两个例子是Dart和Ruby”。 代码导师,2019 年 4 月 [来源]

我们要向Dart社区的所有开发人员表示衷心的感谢。看到您采用 Dart,提供您的反馈,并继续与我们一起探索旅程,因为我们试图为在任何平台上运行的快速应用程序构建最佳的客户端优化语言,这对我们来说意义重大。

用于构建用户界面的新语言功能

说到客户端开发,Dart&Flutter团队之间的长期联合项目之一是为使用Dart捕获用户界面代码创建强大的支持,而无需标记语言。我们认为,对行为和布局使用单一语言有很大的好处。其中包括减少上下文切换,不必学习两种语言,以及在构建UI时允许通用编程语言的所有抽象功能。

在过去的几个版本中,我们进行了一些改进,例如简化用于构造小部件的代码、添加自动整数到双精度转换以及添加集合文字。在 Dart 2.3 中,我们又向前迈出了一大步,有三个新功能用于表达基于列表、条件或重复的 UI。

您可以将 UI 视为小部件节点的树。某些节点包含小部件列表,例如可滚动元素的列表。通常,这些列表是从其他列表构建的。为此,我们添加了一个新的点差运算符功能,用于将元素从一个列表解压缩到另一个列表中。在以下示例中, 返回小部件列表,然后使用 spread 运算符将其解压缩到周围的列表中:buildMainElements()``…

使用展开运算符的 Dart 示例代码

另一个常见的 UI 任务是根据条件包含特定元素。例如,您可能希望在除最后一页之外的所有页面上都包含“下一步”按钮。在 Dart 2.3 中,在以下情况下,您可以使用集合执行此操作:

使用集合的 Dart 示例代码如果

最后,UI 通常从其他重复元素构建重复元素。您可以使用新的功能集合来表达这一点:

Dart 示例代码使用集合

由于这三个新功能是语言功能,而不是标记命令,因此它们是完全可组合的,并且可以在处理集合的任何上下文中使用。这些功能包含在 Flutter 1.5 版本中,并在 Dart 2.3 版本中提供,您可以立即下载。我们还添加了可在静态分析中配置的新 lint,以强制使用新的跨页集合 if特征集合

有关添加这些功能的所有工作的详细信息,请查看Dart语言团队的工程师Bob Nystrom(又名munificentbob)最近的这篇文章

我们还要感谢参与用户体验研究的开发人员,这些研究对塑造这些新的语言功能至关重要。

IDE 和编辑器功能

为了与 Dart 2.3 的 UI 主题保持一致,我们还在 IDE 支持中添加了新的 UI 指南功能。UI 指南是在 UI 代码中绘制的水平和垂直线条,使得更容易看到 Flutter UI build() 方法的树结构。下面是一个示例(来自计算器应用),其中 UI 指南清楚地说明了 UI 是从包含多个键行(每个键行都包含数字键)的展开列构建的。

img

带有 UI 指南的 IDE,用于可视化 UI 代码的树结构

UI 指南在 IntelliJ IDEA 和 Android Studio 插件的 35.2 版本中可用。要启用该功能,请选择设置“首选项”>“语言和框架”>“Flutter > UI 指南”。我们希望在以后的版本中在 VS Code 中提供类似的支持。

最后,我们观察到开发人员经常在他们的 IDE 中使用代码完成作为探索 API 的一种方式。代码完成在探索已导入的库中的 API 时效果很好,但尚未用于尚未导入的库中的 API。我们的工具现在可以支持后一种用例:您可以在任何前缀上调用代码完成,您将看到当前包中的所有 API 的补全、它直接依赖的包以及 SDK。如果从尚未导入的库中选择补全(标记为“自动导入”,如以下动画所示),则该工具会为您添加导入语句。

img

Animation showing code completion & automatic import adding

This new auto-import feature is available in VS Code with the v2.26 plugin, in IntelliJ 2019.1, and the upcoming Android Studio 3.5 release.

New Dart & Pub websites

Last, but certainly not least, we’ve been very busy the last few months building a new website for the Dart platform: dart.dev

img

重新设计 https://dart.dev 主页

这个新网站有一个全新的登录页面,专注于解释Dart平台的核心优势。我们还更新了文档页面,以提供更好的导航和更具视觉吸引力。最后,我们对所有内容进行了大规模的重组,使发现更容易,并为以前缺少的核心内容添加了新页面。

同样,我们在视觉上更新了 Pub 包网站,并将其移动到一个方便的新 URL:pub.dev

我们很乐意听到您对这两个网站的反馈。如果您发现问题或有建议,请在 dart.dev 问题跟踪器pub.dev 问题跟踪器中创建问题。感谢您的支持!

宣布推出Dart 2.2:更快的本机代码,支持集合文字

今天,我们宣布 Dart 2.2 SDK 的稳定版本,这是对 Dart 2 的增量更新,它改进了提前 (AOT) 编译本机代码的性能和新的文字语言设置功能。

img

面向 Flutter 开发人员的 Dart 性能改进

我们将继续努力使AOT编译的代码(如Flutter应用程序)更快。在 Dart 2.1 中,我们减少了类型检查的开销,大大降低了 AOT 编译代码和使用 JIT(实时)编译在 VM 中运行的代码的类型检查成本。

在 Dart 2.2 中,我们特别关注 AOT 编译代码的性能,在微基准测试上将 AOT 性能提高了 11-16%(代价是代码大小增加了 ~1%)。此改进是几个季度为减少静态调用开销而进行的工作的结果。我们优化的 AOT 代码现在能够使用 PC 相对调用(即使用程序计数器)直接调用目标;之前,我们必须对对象池进行多次查找以确定目标地址。当代码包含大量构造函数和静态方法调用(例如创建大量小部件的 Flutter 用户界面代码)时,这些优化特别有用。

飞镖 2.2 设置文字语言功能

Dart 的核心库 () 包含许多用于建模地图列表和对象的集合类。映射是键值对的集合。列表是值的有序序列,其中每个值可以由索引访问,并且可以多次出现。集合是值的无序集合,其中每个值只能出现一次,并且可以有效地检查值是否在集合中。dart:core

Dart 集合通常使用编译时常量进行初始化,因此 Dart 具有用于表达此初始化的方便文本语法。在 Dart 中,列表可以初始化为:

以前,Dart 仅支持列表和映射的文字语法,因此集合的初始化很麻烦,因为我们必须通过列表进行初始化:

此代码不仅不方便且效率低下;缺少文字支持会阻止使货币成为编译时常量。通过 Dart 2.2 对文字的扩展以支持集合,我们可以初始化一个集合并使用方便的新语法使其 const :

有关 Flutter 团队如何开始应用集合文字的真实示例,请参阅 PR #27811。有关如何使用集合文本的更多常规详细信息,请参阅更新的 Dart 2.2 语言教程

使用 Dart 2 通用前端 (CFE) 构建新的语言功能

Dart语言实现 – Flutter使用的Dart VM,dart2js编译器和Dart dev编译器(dartdevc) – 共享一个共同的前端。Dart 公共前端 (CFE) 解析 Dart 代码,执行类型推断,并将 Dart 转换为后端实现接受作为输入的较低级别的中间语言。

集合文字特征是语言结构的一个例子,由于CFE,我们能够快速开发。用于解析集合文字和执行类型推断的代码在 CFE 中为所有 Dart 后端实现了一次。此外,我们构建了一个仅前端过渡实现,最初可以由后端使用。在过渡实现中,上面设置的货币的非常量版本在编译期间被转换为等效的:

常量集文本的过渡实现是不同的,因为常量集不能分段增量构建。相反,我们在一个私有的不可修改的集合类中实现了这一点,该类包装了一个 const map,其中 set 元素是 map 的键:

不可修改的 set 类根据换行映射实现 Set 接口中的方法。

总的来说,我们最初能够将集合文字实现为仅限 CFE 的功能。后端最初可以使用 CFE 实现,然后独立于功能的初始启动开发自己的本机支持。这允许后端推迟其本机支持,直到更好地理解此功能的性能方面。

飞镖 2.2 语言规范

Dart 2 是对 Dart 的实质性升级,我们花了一段时间才更新正式的 Dart 语言规范以匹配我们所做的所有更改。我们终于完成了这项工作,并且该规范是最新的Dart 2.2。我们还将语言规范源代码移动到新的语言存储库,并添加了持续集成,以确保在为 Dart 语言的未来版本发展规范时以 PDF 格式生成滚动草案规范。2.2 和滚动 Dart 2.x 规范均可从 Dart 规范页面获得。

获取飞镖 2.2

Dart SDK 2.2 现已从 Dart 主页获得。如果你是 Flutter 开发人员,Dart 2.2 已经包含在内。(注意:当前的 Flutter master 和 dev 频道将报告 Dart 2.2。今天的 Flutter 1.2 稳定版将发布 Dart 2.1.2;这与 Dart 2.2 具有相同的功能)。

现在就是这样。我们希望您喜欢Dart 2.2!

宣布Dart 2.1:改进的性能和可用性

今天,我们宣布 Dart 2.1 的稳定版本,这是对 Dart 2 的更新,它提供了更小的代码大小、更快的类型检查、更好的类型错误可用性以及新的语言功能,以提高构建用户体验时的工作效率。

img

登陆飞镖 2

Dart 2是对Dart平台的巨大升级。它完成了从我们早期的Web根源到主流编程语言的转变,适用于跨移动和Web快速开发丰富的用户体验。Dart作为一种语言在提供虚拟机(VM)和编译原生机器代码和JavaScript方面有些独特。这支持了各种平台在开发和生产方面的不同需求。

作为向 Dart 2 过渡的一部分,我们添加了一个声音类型系统以支持大型团队构建复杂的应用程序,新的编译器支持以生成针对移动设备优化的本机代码,以及完全重新设计的 Web 平台工具。Dart 为 Flutter 提供支持,这是我们快速增长的工具包,用于从单个代码库为 iOS 和 Android 构建精美的原生体验;它也是谷歌一些最大的项目使用的语言,比如谷歌广告。

自从 Dart 2 在 8 月推出以来,我们一直致力于将整个生态系统引入 Dart 2。我们切换了 dartlang.org 网站,以便在任何地方使用 Dart 2 示例,并提供了用于迁移 Dart 1.x 包的工具和文档。我们知道 Dart 2 中的重大变化涉及现有 Dart 开发人员的迁移工作,我们非常感谢那些帮助我们为未来建立新基础的人。现在,我们的重点转向利用这些投资来提高性能和生产力。

Dart 2.1 语言支持,支持从整数到双精度转换

新的 Flutter 开发人员在指定填充、设置字体大小等时经常被以下分析错误绊倒:

img

从系统的角度来看,这些错误是有意义的:API 需要一种类型(双精度型),开发人员指定不同类型的值(整数)。然而,从可用性的角度来看,这似乎有点愚蠢:从 int 到 double 有一个微不足道的转换,那么为什么不这样做呢?Dart 2.1 现在推断出 int 可以在何处静默地计算为双精度

img

Dart 2.1 语言支持混合

我们还改进了Dart对mixins的支持。如果你以前没有遇到过Dart mixins,那么值得一读Romain Rastel对Dart mixins的精彩介绍。Dart 2.1 引入了 mixins 的新语法,其中包含一个新关键字,可用于定义只能用作 mixins 的类。我们还添加了支持,以便 mixins 可以扩展其他类(以前它们只能扩展),并且可以调用其超类中的方法。mixin``Object

扩展非对象类的一个例子来自 Flutter 的动画 API,其中 – 一个框架类,它提供了一个用于将动画推进单个帧的股票代码 – 声明了一个实现通用 TickerProvider 接口的 mixin。动画仅适用于有状态微件(因为动画中的位置被视为状态)。新的 mixin 支持允许我们通过声明只有扩展 Flutter State 类的类才能使用 mixin 来表达这一点:SingleTickerProviderStateMixin

img

Dart 2.1 编译时类型检查

Dart 2 的声音类型系统在开发过程中保护您,在您违反类型指定的合同时告诉您。例如,假设您正在为 Flutter 创建一个状态类。此类应扩展框架类。类期望传递它包含其状态的类。State``State``StatefulWidget

img

现在,如果您犯了一个编程错误,并且(比如说)将其传递给其后代而不是 ,则类型信息使工具能够捕获错误并立即向您显示警告:StatelessWidget``StatefulWidget

img

这些编辑时类型检查是在 Dart 2.0(由 Dart 分析器提供支持)中添加的。但是,在另一个地方,您可能期望进行这些类型检查,即在编译时,当您执行 Flutter 发布构建时。这些检查在 Dart 2.0 中是不完整的,这可能会导致可用性问题,其中错误的源代码可以在不产生任何错误的情况下编译。在 Dart 2.1 中,这些检查已完成,并且分析器和 Dart 编译器包含相同的检查。

Dart 2.1 对 Flutter 开发人员的性能改进

对于在我们的虚拟机上运行的AOT编译代码(例如Flutter应用程序),Dart 2通常比Dart 1.x更快。但是,在少数边缘情况下,新类型系统添加的综合检查导致了 20-40% 的不良开销。在 Dart 2.1 中,我们大大降低了 AOT 编译代码和使用 JIT(实时)编译在 VM 中运行的代码的类型检查成本。

从中受益的一个具体案例是我们的开发人员工具(使用 VM 运行)。例如,对一个大型基准测试应用程序(基于 Flutter 库的多个级联副本)执行代码分析过去需要 ~41 秒;现在需要 ~25 秒。

面向 Web 开发人员的 Dart 2.1 性能改进

我们还改进了在 Web 上运行的 Dart 代码的代码大小和编译时间。我们专注于 dart2js 的输出大小,并看到了良好的结果,例如我们的一个样本的缩小输出大小减少了 17%,编译时间缩短了 15%。

核心 SDK 之外的更改

除了上述Dart SDK中的更改之外,我们还在核心SDK之外进行了一些令人兴奋的更改。

协议缓冲区(或简称 protobuf)是一种与平台无关的机制,用于序列化结构化数据。它们在谷歌内部被广泛使用,在谷歌之外也得到了广泛的采用——例如作为gRPC的一部分。Dart现在是一种官方支持的protobuf语言,我们在核心协议缓冲区网站上添加了详细的文档,其中包含教程参考文档。

您可能听说过 knative(一个基于 Kubernetes 的平台),用于支持构建、部署和管理无服务器工作负载。我们最近调查了对在 knative 上提供 Dart 代码的支持,并创建了一个小样本。对于大多数 Dart 应用程序开发人员来说,这可能太低级了,但从平台的角度来看,我们发现它非常令人兴奋,并预计这将是在 Google Cloud 中更好地支持 Dart 代码的关键构建块——例如为 Flutter 应用程序创建后端。

获取飞镖 2.1

Dart SDK 2.1 可从 Dart 主页获得。如果您是 Flutter 开发人员,Dart 2.1 包含在即将发布的 Flutter 1.0 版本中。

我们还更新了 DartPad 以运行 Dart 2.1,并添加了 int-to-doublemixins 的示例。

下一步是什么

我们希望发布几个利用 Dart 2 平台基础的 2.x 版本。我们将基于框架合作伙伴和应用开发人员的需求。2019年,我们预计将调查以下领域:

  • Dart 语言的持续发展:对于 Dart 2.2,我们正在研究许多更改,例如对 const 表达式的改进以及对新 Set 文本的支持。在 2.2 之后,我们正在研究对 Unicode 字符串的支持,并正在研究我们是否可以提供更好的空安全性。
  • 优化 Dart 作为创建用户界面的语言的进一步改进:Dart 2 以其新的类型系统和可选的新 Dart 2.1 添加了 int 到双倍值推理,我们目前正在研究一些潜在的改进,例如支持小部件列表中的条件将对象集合扩展到其他集合, 甚至可能消除用分号终止语句的需要
  • 更好的性能:我们将继续减小已编译的 Dart 代码的大小和性能,包括更好地支持使用多核处理器,进一步减小代码大小以缩短下载和启动时间,并可能更好地控制大小或运行时性能是否最关键。

有关 Dart 和 Flutter 的更多信息,我们希望您加入我们的 Flutter Live,这是一个将于 12 月 4 日举行的在线活动,将在网络上直播。我们很高兴与您分享更多关于路线图的信息。

现在就是这样。我们希望您喜欢Dart 2.1!


Dart2.18 :https://medium.com/dartlang/dart-2-18-f4b3101f146c

发表评论

邮箱地址不会被公开。 必填项已用*标注