Flutter 3SDK版本嵌入Dart 2.17——提升工作效率

147 阅读10分钟

今天在谷歌I/O大会上,我们宣布了一个新的Dart SDK,即2.17版。这个版本建立在我们的核心主题上,即领先的生产力和平台可移植性。它提供了新的语言特性:支持成员的枚举,改进了对超类的参数转发,以及对命名参数的更多灵活性。我们通过package:lints的一个新的主要版本改进了工具--我们的工具支持根据我们的最佳实践检查Dart代码--并通过丰富的代码样本广泛更新了核心库API文档。为了改善平台集成,我们在Flutter插件中使用dart:fi(本地C互操作)的新模板,对RISC-V处理器的实验性支持,以及对macOS和Windows可执行文件的支持。

Dart 2.17 reease banner

新的语言功能,提高生产力

我们不断地发展Dart语言,使你更有生产力--通过增加新的功能和改进现有功能。Dart 2.17增加了对枚举成员的新支持,改进了在构造函数中使用命名参数的方式,并使转发参数到超类的代码不再那么冗长和重复了。

带有成员的增强型枚举

枚举很适合代表一组离散的状态。例如,我们可以将水建模为enum Water { frozen, lukewarm, boiling }。但是如果我们想在枚举上添加一些方法--例如,将每个状态转换为温度,并支持将枚举转换为字符串,该怎么办?我们也许可以使用扩展方法来添加一个waterToTemp()方法,但是我们必须注意保持与枚举的同步性。对于字符串的转换,我们更倾向于覆盖toString(),但这并不被支持。

在Dart 2.17中,我们现在对枚举的成员有了普遍的支持。这意味着我们可以添加持有状态的字段、设置状态的构造函数、具有功能的方法,甚至可以覆盖现有的成员。你们中的许多人一直在要求这项功能;它是我们在语言跟踪器中投票率第三高的问题

对于我们的水的例子,我们可以添加一个保存温度的int字段和一个接收int的默认构造函数。

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

为了确保构造函数在枚举创建时被调用,我们需要为每个枚举值调用它。

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

为了支持转换为字符串,我们简单地覆盖toString,枚举继承自Object。

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

这样,你就有了一个完整的枚举,可以很容易地被实例化,并且你可以调用方法。

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

下面是这两种方法的一个完整例子;我们发现新的Dart 2.17版本更容易阅读和维护。

超级初始化器

当你有一个类的继承层次时,一个常见的模式是将一些构造函数参数传递给超类的构造函数。要做到这一点,子类需要:1)在自己的构造函数中列出每个参数;2)用这些参数调用超类的构造函数。这就导致了模板代码:大量的重复,使得代码更难阅读,维护起来更麻烦。

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

到处都是命名的args

最后,我们改进了当你调用一个方法时命名参数的工作方式。以前,这些参数必须出现在方法的参数列表的最后。这在有些情况下是令人讨厌的,因为你更愿意把一个位置参数放在最后,以使代码更易读。例如,请看下面的List.generate构造函数的调用--以前,可增长参数必须放在最后,这使得它很容易在包含生成器本身的大型位置参数下面被忽略。现在你可以按照你的喜好来排序,允许你把小的命名参数放在前面,把生成器放在最后。

关于这三个特性在动作中的进一步例子,请看我们更新的枚举超级初始化器命名参数的样本。

生产力工具

延续生产力的主题,我们在核心工具方面有一些改进。

在Dart 2.14中,我们引入了package:lints,它与Dart分析器一起工作,帮助你编写Dart代码,以防止错误,并使用规范的风格,使代码审查更加有效。从那时起,分析器中出现了许多新的衬垫,我们仔细地对这些衬垫进行了筛选,从中选出了10个适用于所有Dart代码的新衬垫,以及两个专门用于Flutter代码的新衬垫。其中包括确保你的导入被包含在你的pubspec文件中,防止滥用类型参数的空值检查,以及确保子属性的风格一致。你可以通过一个简单的命令升级到新的衬线。

  • 对于Dart包
    :dart pub upgrade --major-versions lints

  • 对于Flutter包:
    flutter pub upgrade --major-versions flutter_lints

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

由dart doc工具生成的API文档是大多数Dart开发者学习新API的重要资产。虽然我们的核心库API长期以来都有丰富的文字描述,但许多开发人员告诉我们,他们更喜欢通过阅读使用API的示例代码来学习API。在Dart 2.17中,我们对所有主要的核心库进行了彻底的改造,在浏览量最大的前200个页面中增加了示例代码,因此它们现在都有全面的示例代码。作为一个例子,比较一下Dart2.16中dart:convert的文档和Dart 2.17的更新页面;希望这能使文档更容易被使用。

生产力的提高不仅来自于我们在平台上添加新的功能,也来自于我们清理我们的堆栈和删除不再使用的功能。这有助于保持我们的表面积很小,这对新的开发者来说尤其关键。为此,我们已经从dart:io库中删除了231行废弃的代码--如果你还在使用这些废弃的API,你可以通过dart fix升级到它们的替代版本。我们还继续努力删除被废弃的Dart CLI工具,这次我们删除了dartdoc工具(使用dart doc代替)和pub工具(使用dart pub或flutter pub)。

扩大我们的平台整合和支持

第二个核心主题是平台整合和支持。Dart是一种真正的多平台语言。虽然我们已经支持广泛的平台,但我们也在不断发展,以确保你能与每个支持的平台深度整合,同时也支持新兴平台。

Dart FFI--我们与C/native代码互操作的核心机制--是将Dart代码与现有原生平台代码集成的一种流行方式。在Flutter上,这可能是一个很好的方式来建立使用主机平台的本地API的插件(如Windows win32 APIs)。在Dart 2.17和Flutter 3中,我们在flutter工具中增加了模板,因此您现在可以轻松地创建FFI插件,这些插件有Dart API支持,通过dart:fi调用到本地代码。详情请见flutter.dev上更新的开发包和插件页面。

为了能够在具有ABI(应用程序二进制接口)特定类型的平台上使用FFI,FFI现在支持ABI特定类型。例如,您现在可以使用Long(C语言中的long)来正确表示一个具有ABI特定大小的长整数,根据CPU架构,它可能是32位或64位。关于支持类型的完整列表,请参见AbiSpecificIntegerAPI页面中的 "实施者 "列表。

当使用Dart FFI与本地平台深度集成时,你有时需要将Dart和本地代码分配的内存或其他资源(端口、文件等)的清理工作对齐。这在历史上是非常棘手的,因为Dart是一种垃圾收集语言,可以自动处理清理工作。Dart 2.17通过引入Finalizer的概念来解决这个问题,它包括一个Finalizable标记接口,用于 "标记 "不应该被最终确定或过早丢弃的对象,还有一个NativeFinalizer类,可以附加到Dart对象上,在该对象即将被垃圾收集时提供一个回调运行。这些都允许在本地和Dart代码中运行清理代码。详情请参见NativeFinalizer的API文档中的描述和例子,或者WeakReferencesFinalizer的文档,以了解对普通Dart代码的类似支持。

我们对Dart编译为本地代码的支持是使Flutter应用程序具有良好的启动性能和快速渲染的核心推动因素。第二个用例是用dart compile将Dart编译成可执行文件的能力。这些可执行文件可以在任何机器上独立运行,而不需要安装Dart SDK。Dart 2.17的另一个新功能是支持对可执行文件的签名,这使得在通常需要签名的Windows和MacOS上的部署成为可能。

我们还在继续扩大我们的支持平台集,保持在新的新兴平台的最前沿。RISC-V是一种新的创新型处理器指令集。RISC-V国际组织是一个全球性的非营利组织,拥有RISC-V规范,使指令集免费和开放。这仍然是一个新兴的平台,但我们对它的潜力感到兴奋,所以我们的2.17.0-266.1.beta Linux版本(或以后从我们的测试频道)包括对它的试验性支持。我们很想听到你的反馈,所以请提出问题发表你的经验!

开始使用Dart 2.17!

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

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