在11月20号,官方发布了健全的空安全Beta版本。空安全作为近期最具生产力的功能,可以帮助大家避免空异常问题。
官方已经迁移Dart核心库,Flutter framework和超过40个Dart Flutter Packages支持空安全。
大家在使用过程中发现任何问题都可以在feedback反馈。
当你将flutter sdk版本的最低版本至少2.12着意味着你的app或者package仅支持空安全。
environment:
sdk: ">=2.12.0-0 <3.0.0"
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;
^
以上代码展示了在修改flutter最低版本前后,编译器所做的不同表现和提示。
空安全迁移
- 依赖检查
官方建议按照依赖顺序进行修改,避免上层依赖api的二次修改。为了检查某个依赖是否已经迁移完毕,可以使用dart pub outdated --mode=null-safety,如下所示:
如果在minor新版中依赖支持了空安全,那么在Upgradable列中会展示新版本库。如果在修改了major版本号的新依赖库支持了空安全,那么在Resolvable列中会展示该库。
在pub.dev库中可以勾选Supports null safety选项来过滤支持了空安全的库。
-
使用迁移工具
如果你的依赖已经准备完毕,那么就可以使用dart migrate对推断出来的会为空的属性进行人工检查,如果不认可工具的修改提示,则可以认为进行修正。
-
静态分析已迁移代码
使用pub get命令更新packages,然后静态分析已迁移代码:
Dart code:
dart pub get
dart analyze
Flutter code:flutter pub get
flutter analyze Ensure tests pass
检查测试用例中出现的对于null的判断,也许需要修改为不再允许出现null值。
-
发布空安全包
在迁移完成和测试用例通过之后,你可以发布一个预发布版本。提高包的主版本号,比如2.3.0为3.0.0,既能让使用者在准备充分之后升级,也能给开发者足够的时间去重构API。
预发布版本版本号规则,比如使用use 3.0.0-nullsafety.0, not 3.0.0
健全的空安全的好处
更安全的代码
官方给出了以下如下内部评审实际的发现的问题作为例子:
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) {
...
对于以上代码,如果独立来看也许会发现major和minor肯能会为null,但是在实际代码review过程中也一直没有发现问题。但是现在对于空安全静态分析会直接给出错误提示。
除了上诉例子以外,还有其他问题如下:
- 内部团队发现针对空安全判断不会为null的值依然有判空的代码。这种情况比较多的出现在protobuf中,对于未设置值的可选字段,只会返回默认的非null值,这就使得部分开发者会做出不正确的默认判断条件,混淆了默认值和null值。
- 在Flutter代码中,如果访问widget的context之外的状态对象,在空安全之前,这将会返回null并且不易被发现,在空安全检查之后,将被认为不会为null并且抛出分析错误。
- flutter团队发现flutter引擎存在一个bug,如果传递一个null给Window.render()的scene参数,就会报错。然后在空安全迁移的时候可以将该参数标记为非null。
编译空安全项目的杠杆作用
健全的空安全可以使编译器利用可空性信息使编译出来的代码更小更快。
对于最简单的hello world项目,在未压缩情况下体积可以减少3.5%安装包大小,而对于Flutter Framework则可以减少3.9%。
至于代码速度,强制的健全的类型系统可能会增加开销,适当的空检查也可以提升代码执行速度。基于benchmark的初始化分析表示和之前的发布版本也处于同一水平,但是新的类型信息也为将来的新的性能提升提供了可能。