Dart 健全的空安全: Beta 版
作者 / Michael Thomsen, Dart & Flutter Product Manager, Google
我们为 Dart 和 Flutter 带来了健全的空安全 Beta 版。空安全是提升生产力的最新功能,可帮助您避免空值错误,这类错误通常很难发现。想快速了解我们对空安全如此期待的原因,请观看这支视频:
健全的空安全
https://dart.cn/null-safety
腾讯视频链接
https://v.qq.com/x/page/n3208kis0wj.html
Bilibili 视频链接
https://www.bilibili.com/video/BV1GV411Y7sW/
随着空安全 Beta 版的发布,是时候开始动员社区对 pub.dev 上的数千个 package 进行迁移了。我们已经迁移了 Dart 核心库、Flutter 框架以及超过 40 个 Dart 和 Flutter package。同时我们希望社区也能开始迁移 package,拥抱空安全。
pub.dev
https://pub.flutter-io.cn/
空安全 package
https://pub.flutter-io.cn/packages?q=&prerelease-null-safe=1
在 Beta 版的基础上,我们也开始向空安全的稳定版发起冲刺。希望您能够开始使用空安全,并告诉我们任何可以改进之处,包括界面消息是否易于理解,或者文档是否清晰易读。我们非常期待您的反馈。
提交反馈
https://github.com/dart-lang/sdk/issues/new?title=Null%20safety%20feedback:%20[issue%20summary]&labels=NNBD&body=Describe%20the%20issue%20or%20potential%20improvement%20in%20detail%20here
启用空安全
在讨论空安全迁移之前,我们需要重申 (如我们的空安全原则中所述),何时开始采用空安全完全由您来决定。如果应用和 package 的最低 Dart SDK 版本约束为 Dart 2.12 预发布版或更高版本,它们将默认以空安全状态运行:
空安全原则
https://dart.cn/null-safety#null-safety-principles
启用空安全
https://dart.cn/null-safety#enable-null-safety
environment:
sdk: ">=2.12.0-0 <3.0.0"
如需体验空安全,请尝试创建 (例如,使用 dart create) 一个包含如下代码的小型空安全 hello 应用。然后,您可以尝试在更改 SDK 约束并运行 dart pub get 前后分别运行该应用,来体验程序行为的变化。(请确保使用 dart –version 命令,返回的是 2.12 的 SDK 版本)
bin/hello.dart:
...
void main() {
var hello = 'Hello Dart developers';
if (someCondition) {
hello = null;
}
print(hello);
}
Before changing the SDK constraint:
$ dart run
null
After changing the SDK constraint (and running dart pub get):
$ dart run
bin/hello.dart:6:13: Error: Null can't be assigned to a variable of type 'String' because 'String' is not nullable.
hello = null;
^
迁移至空安全
要将 package (或简单应用) 迁移至空安全,请按照以下五个步骤进行操作,详细的内容说明请查看迁移指南:
https://dart.cn/null-safety/migration-guide
第 1 步: 检查以确保依赖项已就绪
我们强烈建议按顺序迁移代码,首先迁移依赖关系图中的子项。如下图所示,如果 C 依赖于 B,而 B 依赖于 A,那么应首先将 A 迁移到空安全,然后再依次迁移 B 和 C。无论 A、B 和 C 是库、package 还是应用,该顺序都适用。
迁移顺序为何如此重要?虽然您可以在迁移依赖项之前先处理一些代码迁移工作,但如果依赖项在迁移期间更改了其 API,那么您将面临必须重新执行迁移的风险。如果您的某些依赖项没有支持空安全,请考虑使用 pub.dev 上 package 所给出的联系方式与 package 发布者联系。
验证依赖项是否已就绪
要验证您的应用或 package 是否已准备好开始迁移,您可以在空安全模式下使用 dart pub outdated。比如下图所示应用,只需将其依赖项 path、process 和 pedantic 升级到 Resolvable 列中给出的预发布版本,就表示已做好了迁移的准备。
如果依赖项的小版本升级已经提供了空安全支持,则会显示在 Upgradable 列中。空安全支持通常由大版本更新来提供,这时 outdated 输出结果的 Resolvable 下方将列出相应的版本。要升级到这些版本,请编辑 pubspec.yaml 文件以允许获取这些大版本更新。例如,将 process: ^3.0.13 更改为 process: ^4.0.0-nullsafety。
您还可以在 pub.dev 上的 package 页面使用新的 Null safety 标签查看支持空安全的 package (例如 collection 1.15),我们还在高级搜索中提供了新的空安全搜索选项 (如下图所示)。
collection 1.15
https://pub.flutter-io.cn/packages/collection/versions/1.15.0-nullsafety.5
空安全搜索选项
https://pub.flutter-io.cn/packages?q=&prerelease-null-safe=1
第 2 步: 使用迁移工具进行迁移
依赖项准备就绪后,您就可以使用迁移工具 dart migration 来迁移应用或 package 了。
迁移工具是交互式的,您可以查看工具推断出的可空属性。如果您对工具给出的结论有异议,则可以添加可空性提示以更改推断。适当添加迁移提示有可能大幅提升迁移质量。
我们曾安排少量的 Dart package 作者使用空安全的早期预览版进行了测试性迁移,并取得了颇为积极的结果。迁移指南中给出了更多迁移工具的使用技巧。
迁移指南
https://dart.cn/null-safety/migration-guide
第 3 步: 静态分析迁移后的代码
在 IDE 或命令行中使用 pub get 更新 package。然后使用 IDE 或命令行对您的 Dart 代码执行静态分析:
$ dart pub get
$ dart analyze
如果是 Flutter 代码,执行静态分析的命令如下:
$ flutter pub get
$ flutter analyze
第 4 步: 确保测试通过
运行测试,并确保测试通过。如果您曾将 package 代码更改为不再允许为空,则可能需要更新可接受空值的测试。
第 5 步: 发布您的空安全 package
迁移完成且测试通过后,您便可以将 package 发布为预发布版。这里简单给出两种最佳做法供参考:
将您的版本号升至下一个大版本 (例如,从 2.3.x 到 3.0.0)。此最佳做法可确保您的 package 用户不会在尚未做好使用空安全的准备时就升级至该版本,并且使您可以自由重构 API 以最充分地利用空安全。
将 package 在 pub.dev 上以预发行的方式进行发布。(例如,使用 3.0.0-nullsafety.0,而非 3.0.0)
以预发行的方式发布
https://dart.cn/tools/pub/publishing#publishing-prereleases
有关迁移和发布版本的详细信息,请参阅迁移指南:
https://dart.cn/null-safety/migration-guide
健全空安全的优势
在之前 Dart 和 Flutter 空安全支持的技术预览版中,我们结合大量示例探讨了空安全的优势。随着空安全的逐步完成,我们将分享给大家一些真实案例中看到的空安全的优势。
代码安全性提升
就在最近,我们在 Flutter 的 master 渠道中发现了一个错误,多个 flutter 工具命令在特定计算机配置下会因为空值错误发生崩溃: The method ‘>=’ was called on null。根本问题源于近期的一项拉取请求 (PR),用于添加对 Android Studio 4.1 的检测。该 PR 添加了如下代码:
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) {
…
您能发现里面的问题吗?因为 version 可能为空,major 和 minor 也都可能为空。如果单独检查这段代码,这个错误似乎并不难发现。但实际上,即使经过了严格的代码审查 (如 Flutter repo 所用代码审查流程),也总是难免有这样的漏网之鱼。借助空安全,静态分析能够立即捕捉到这一问题:
Dartpad 捕捉此问题的演示
https://dartpad.cn/0e9797be7488d8ec6c3fca92b7f2740f
这只是一个非常简单的错误。在 Google 内部早期使用空安全代码时,捕捉并解决的复杂错误远不止于此。例如:
一个内部团队发现,他们经常在代码中检查是否存在空值,但空安全知道那些值永远不会为空。这一状况常见于使用 protobuf 的代码,在这些代码中,可选字段在未经设置时会返回默认值,而永远不会为空。这会导致代码混淆默认值和空值,并错误地检查默认条件。
Google Pay 团队在他们的 Flutter 代码中发现了一些错误,在尝试访问 Widget 上下文之外的 Flutter State 对象时会出错。在引入空安全之前,这些代码会返回空值并掩盖错误;通过空安全健全的分析,确定这些属性永远不会为空,并抛出分析错误。
Flutter 团队发现了一个错误,如果向 Window.render() 中的 scene 参数传递空值,则 Flutter 引擎可能会崩溃。在进行空安全迁移期间,他们添加了一个提示以将 Scene 标记为不可空,然后便可轻松防止传递空值可能会引发的应用崩溃问题。
Protocol Buffers
https://developers.google.cn/protocol-buffers
将 Scene 标记为不可空
https://github.com/cbracken/engine/blob/bad869e229a8a02cad6e63d12e80807b33b5c12f/lib/ui/window.dart#L1069
编译过程受益于健全的空安全
Dart 空安全的健全性还暗含了另一项广受好评的优势: 这意味着 Dart 编译器可以利用可空信息做出优化。这有可能使您的程序更加小巧而快速。完全迁移到健全的空安全的真实应用目前并不多 (因为我们现在才刚刚开始在生态系统内推进 package 的迁移,而很多应用依赖于这些 package),但从核心框架来看,我们得到了十分令人鼓舞的结果。
最近,我们对 hello_world 示例应用进行了重新编译测试,以衡量空安全对应用大小的影响。它是一个仅仅显示 “hello world” 的简单示例。对比编译后的代码总大小可以发现,在仅仅采用健全的空安全重新编译而无任何其他措施的情况下,未压缩 (安装在设备上) 的代码大小缩减了 3.5%。在只有 10 行代码的应用中实现这一成果,其原因是该应用所包含的所有库的代码大小都得到了缩减。例如 Flutter 框架本身 (package:flutter) 就缩减了 3.9%。
hello_world 示例应用
https://github.com/flutter/flutter/blob/master/examples/hello_world/lib/main.dart
应用大小比较
https://gist.github.com/mit-mit/64e160f9dc3bf6c69c7ef2f81384594a
代码运行速度方面,如果必须强制执行健全类型系统,则可能会增加开销。但是,由于空值检查变少,因此也可能会提高代码运行的速度。我们初步的基准分析表明,性能与以前的版本处于同等水平,并且新的附加类型信息为我们将来实现新的性能提升带来了可能性。我们计划在未来更详细地和大家分享在性能提升方面所做的工作。
在某些情况下,我们已经看到空安全可以提高性能,特别是在向空安全迁移的过程中发现代码逻辑中的缺陷。例如,我们在 Flutter web 的文本布局缓存中发现了一个问题。此缓存使用了一个可空的键,然后某些逻辑会在出现空值时使用 TextAlign.start。这种逻辑在缓存中造成了一个缺陷: 元素虽保有默认值,但看起来却像发生了变化。其结果是频繁出现缓存未命中的情况。添加不可空的 textAlign getter 有助于修复缓存缺陷,在文本得到缓存的情况下,其渲染性能提高了 14 倍。
即刻开始体验!
Dart 和 Flutter 空安全的 Beta 版已经发布,如果您使用 Flutter 进行开发,可以通过 flutter channel beta 切换到 Beta 版,然后执行 flutter upgrade。您也可以从 Dart SDK 归档页面中获取独立的 Dart SDK。
Dart SDK 归档
https://dart.cn/tools/sdk/archive#beta-channel
如果您是 package 作者,建议您阅读我们的迁移指南并制定迁移计划。如果您有任何疑问或建议,请告诉我们。
迁移指南
https://dart.cn/null-safety/migration-guide
提供反馈
https://github.com/dart-lang/sdk/issues/new?title=Null%20safety%20feedback:%20[issue%20summary]&labels=NNBD&body=Describe%20the%20issue%20or%20potential%20improvement%20in%20detail%20here
如果您是应用开发者,可以暂缓迁移并等待空安全进入稳定版。我们计划尽快解决在 Beta 版本中收集到的反馈,并修复所有遗留问题。现在很难为空安全的稳定版本设定一个具体的时间表,但我们正在考虑于明年年初发布。
感谢您一直以来的支持与反馈,帮助我们使 Dart 成为更加高效可靠的语言,使 Flutter 成为更加强大的框架!也欢迎大家继续在评论区和我们分享您的想法和建议!
推荐阅读
点击屏末 | 阅读原文 | 访问 Flutter 开发者社区中文资源
原文地址: https://blog.csdn.net/jILRvRTrc/article/details/110600083
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章