在11月20號,官方發(fā)布了健全的空安全Beta版本??瞻踩鳛榻谧罹呱a(chǎn)力的功能,可以幫助大家避免空異常問題。
官方已經(jīng)遷移Dart核心庫,F(xiàn)lutter framework和超過40個Dart Flutter Packages支持空安全。

大家在使用過程中發(fā)現(xiàn)任何問題都可以在feedback反饋。
當(dāng)你將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最低版本前后,編譯器所做的不同表現(xiàn)和提示。
空安全遷移
- 依賴檢查

官方建議按照依賴順序進(jìn)行修改,避免上層依賴api的二次修改。為了檢查某個依賴是否已經(jīng)遷移完畢,可以使用dart pub outdated --mode=null-safety,如下所示:

如果在minor新版中依賴支持了空安全,那么在Upgradable列中會展示新版本庫。如果在修改了major版本號的新依賴庫支持了空安全,那么在Resolvable列中會展示該庫。
在pub.dev庫中可以勾選Supports null safety選項(xiàng)來過濾支持了空安全的庫。

-
使用遷移工具
如果你的依賴已經(jīng)準(zhǔn)備完畢,那么就可以使用dart migrate對推斷出來的會為空的屬性進(jìn)行人工檢查,如果不認(rèn)可工具的修改提示,則可以認(rèn)為進(jìn)行修正。

-
靜態(tài)分析已遷移代碼
使用pub get命令更新packages,然后靜態(tài)分析已遷移代碼:
Dart code:
dart pub get
dart analyze
Flutter code:flutter pub get
flutter analyze Ensure tests pass
檢查測試用例中出現(xiàn)的對于null的判斷,也許需要修改為不再允許出現(xiàn)null值。
-
發(fā)布空安全包
在遷移完成和測試用例通過之后,你可以發(fā)布一個預(yù)發(fā)布版本。提高包的主版本號,比如2.3.0為3.0.0,既能讓使用者在準(zhǔn)備充分之后升級,也能給開發(fā)者足夠的時間去重構(gòu)API。
預(yù)發(fā)布版本版本號規(guī)則,比如使用use 3.0.0-nullsafety.0, not 3.0.0
健全的空安全的好處
更安全的代碼
官方給出了以下如下內(nèi)部評審實(shí)際的發(fā)現(xiàn)的問題作為例子:
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) {
...
對于以上代碼,如果獨(dú)立來看也許會發(fā)現(xiàn)major和minor肯能會為null,但是在實(shí)際代碼review過程中也一直沒有發(fā)現(xiàn)問題。但是現(xiàn)在對于空安全靜態(tài)分析會直接給出錯誤提示。

除了上訴例子以外,還有其他問題如下:
- 內(nèi)部團(tuán)隊(duì)發(fā)現(xiàn)針對空安全判斷不會為null的值依然有判空的代碼。這種情況比較多的出現(xiàn)在protobuf中,對于未設(shè)置值的可選字段,只會返回默認(rèn)的非null值,這就使得部分開發(fā)者會做出不正確的默認(rèn)判斷條件,混淆了默認(rèn)值和null值。
- 在Flutter代碼中,如果訪問widget的context之外的狀態(tài)對象,在空安全之前,這將會返回null并且不易被發(fā)現(xiàn),在空安全檢查之后,將被認(rèn)為不會為null并且拋出分析錯誤。
- flutter團(tuán)隊(duì)發(fā)現(xiàn)flutter引擎存在一個bug,如果傳遞一個null給Window.render()的scene參數(shù),就會報錯。然后在空安全遷移的時候可以將該參數(shù)標(biāo)記為非null。
編譯空安全項(xiàng)目的杠桿作用
健全的空安全可以使編譯器利用可空性信息使編譯出來的代碼更小更快。
對于最簡單的hello world項(xiàng)目,在未壓縮情況下體積可以減少3.5%安裝包大小,而對于Flutter Framework則可以減少3.9%。
至于代碼速度,強(qiáng)制的健全的類型系統(tǒng)可能會增加開銷,適當(dāng)?shù)目諜z查也可以提升代碼執(zhí)行速度?;赽enchmark的初始化分析表示和之前的發(fā)布版本也處于同一水平,但是新的類型信息也為將來的新的性能提升提供了可能。