內容

移轉至空安全

此頁面說明如何以及何時將程式碼移轉至 Null 安全性。以下是移轉您擁有的每個套件的基本步驟:

  1. 等待 您依賴的套件進行移轉。
  2. 移轉 套件程式碼,建議使用互動式移轉工具。
  3. 靜態分析 套件程式碼。
  4. 測試 以確保變更正常運作。
  5. 如果套件已在 pub.dev 上,發布 Null 安全版本作為預發行版本。

若要非正式地了解使用移轉工具的體驗,請觀看此影片

1. 延後遷移

#

我們強烈建議依序移轉程式碼,先移轉依賴圖形的葉節點。例如,如果套件 C 依賴套件 B,而套件 B 依賴套件 A,則應先將 A 移轉至 Null 安全性,然後依序為 B 和 C 移轉。

Illustration of C/B/A sentence

雖然您 可以在依賴項支援 Null 安全性之前進行移轉,但當依賴項移轉時,您可能必須變更程式碼。例如,如果您預測函式會採用可為 Null 的參數,但套件將其移轉為不可為 Null,則傳遞可為 Null 的引數會變成編譯錯誤。

本節說明如何使用空安全模式中的 dart pub outdated 指令,檢查和更新套件的相依性。這些說明假設您的程式碼在原始碼控管之下,這樣您才能輕鬆地復原任何變更。

切換到 Dart 2.19.6 發行版

#

切換到 Dart SDK 的2.19.6 版本。這包含在 Flutter 3.7.12 SDK 中。

檢查您是否有 Dart 2.19.6

$ dart --version
Dart SDK version: 2.19.6

檢查相依性狀態

#

使用下列指令取得套件相依性的遷移狀態

$ dart pub outdated --mode=null-safety

如果輸出顯示所有套件都支援空安全,則您可以開始進行遷移。否則,請使用可解決欄位來尋找空安全版本(如果存在)。

以下是簡單套件輸出的範例。每個套件的綠色勾選版本都支援空安全

Output of dart pub outdated

輸出顯示套件的所有相依性都有可解決的預發行版本,支援空安全。

如果您的套件相依性尚未支援空安全,我們建議您聯絡套件擁有者。您可以在 pub.dev 上的套件頁面找到聯絡方式。

更新相依性

#

在遷移套件程式碼之前,請將其相依性更新為空安全版本

  1. 執行 dart pub upgrade --null-safety 以升級到支援空安全的最新版本。注意:此指令會變更您的 pubspec.yaml 檔案。

  2. 執行 dart pub get

2. 遷移

#

您的程式碼需要進行的大部分變更都很容易預測。例如,如果變數可以為 null其類型需要加上 ? 字尾。如果命名參數不應該是可為 null 的,請將其標記為 required 或給予其 預設值

您有兩種遷移選項

使用遷移工具

#

遷移工具會取得 Null-unsafe Dart 程式碼的套件,並將其轉換為 Null Safety。您可以透過將 提示標記 加入 Dart 程式碼,來引導工具的轉換。

在啟動工具前,請務必做好準備

  • 使用 Dart SDK 的 2.19.6 版本。
  • 使用 dart pub outdated --mode=null-safety,以確保所有相依性都是 Null Safety 且為最新版本。

在包含套件的 pubspec.yaml 檔案的目錄中執行 dart migrate 指令,以啟動遷移工具

$ dart migrate

如果您的套件已準備好進行遷移,則工具會產生類似以下的列

View the migration suggestions by visiting:

  http://127.0.0.1:60278/Users/you/project/mypkg.console-simple?authToken=Xfz0jvpyeMI%3D

在 Chrome 瀏覽器中瀏覽該 URL,以查看互動式 UI,您可以在其中引導遷移程序

Screenshot of migration tool

對於每個變數和類型註解,您可以看到工具推斷出的可空性。例如,在前面的螢幕截圖中,工具推斷第 1 行中的 ints 清單(以前是 int 清單)是可空的,因此應該是 int? 清單。

了解遷移結果

#

如需查看每個變更(或未變更)的原因,請在 建議的編輯 窗格中按一下其行號。原因會顯示在 編輯詳細資料 窗格中。

例如,請考慮以下 Null Safety 之前的程式碼

dart
var ints = const <int>[0, null];
var zero = ints[0];
var one = zero + 1;
var zeroOne = <int>[zero, one];

當此程式碼位於函式外部時(函式內部不同),預設遷移是向後相容的,但並非理想

dart
var ints = const <int?>[0, null];
var zero = ints[0];
var one = zero! + 1;
var zeroOne = <int?>[zero, one];

按一下 第 3 行 連結,您可以看到遷移工具加入 ! 的原因。由於您知道 zero 不可能是 Null,因此您可以改善遷移結果。

改善遷移結果

#

當分析推斷出錯誤的可空性時,您可以透過插入暫時提示標記來覆寫其建議的編輯

  • 在遷移工具的 編輯詳細資料 窗格中,您可以使用 新增 /*?*/ 提示新增 /*!*/ 提示 按鈕插入提示標記。

    這些按鈕會立即將註解新增到您的檔案,而且 沒有復原 功能。如果您不想要工具插入的提示,您可以使用您平常的程式碼編輯器將其移除。

  • 即使工具仍在執行,您也可以使用編輯器新增提示標記。由於您的程式碼尚未選擇加入 Null Safety,因此您無法使用新的 Null Safety 功能。不過,您可以進行不依賴 Null Safety 功能的變更,例如重構。

    編輯完程式碼後,請按一下 從來源重新執行,以採用您的變更。

下列表格顯示可使用的提示標記,以變更遷移工具建議的編輯。

提示標記對遷移工具的影響
expression /!/! 新增到已遷移的程式碼,將 expression 轉換為其基礎的非可為空類型。
type /!/type 標記為非可為空。
/*?*/將前一個類型標記為可為空。
/*late*/將變數宣告標記為 late,表示其有延遲初始化。
/*late final*/將變數宣告標記為 late final,表示其有延遲且一次性的初始化。
/*required*/將參數標記為 required

單一提示會在程式碼的其他地方產生漣漪效應。在先前的範例中,手動在 zero 指定其值(第 2 行)的地方新增 /*!*/ 標記,會讓遷移工具將 zero 的類型推論為 int,而不是 int?。此類型變更會影響直接或間接使用 zero 的程式碼。

dart
var zero = ints[0]/*!*/;

使用上述提示後,遷移工具會變更其建議的編輯,如下列程式碼片段所示。第 3 行不再於 zero 之後有 !,而在第 4 行 zeroOne 被推論為 int 的清單,而不是 int?

第一次遷移使用提示的遷移
dart
var ints = const <int?>[0, null];
var zero = ints[0];
var one = zero! + 1;
var zeroOne = <int?>[zero, one];
dart
var ints = const <int?>[0, null];
var zero = ints[0]/*!*/;
var one = zero + 1;
var zeroOne = <int>[zero, one];

退出檔案

#

雖然我們建議一次全部遷移,但有時並不可行,特別是在大型應用程式或套件中。若要退出檔案或目錄,請按一下其綠色核取方塊。稍後,當您套用變更時,每個已退出的檔案都將保持不變,只會有一個 2.9 版本註解

如需有關遞增遷移的更多資訊,請參閱 不健全的空安全

請注意,只有完全遷移的應用程式和套件與 Dart 3 相容。

套用變更

#

當您滿意遷移工具建議的所有變更時,請按一下套用遷移。遷移工具會刪除提示標記並儲存已遷移的程式碼。該工具也會更新 pubspec 中的最低 SDK 約束,讓套件採用空安全。

下一步是 靜態分析您的程式碼。如果有效,請 測試您的程式碼。然後,如果您已在 pub.dev 上發布您的程式碼,請 發布空安全預發行版本

手動遷移

#

如果您不想使用遷移工具,您可以手動遷移。

我們建議您先遷移葉面函式庫,也就是不會從套件中匯入其他檔案的函式庫。然後遷移直接依賴葉面函式庫的函式庫。最後遷移具有最多套件內依賴項的函式庫。

例如,假設您有一個 lib/src/util.dart 檔案,它會匯入其他(空安全)套件和核心函式庫,但沒有任何 import '<local_path>' 指令。考慮先遷移 util.dart,然後再遷移僅依賴 util.dart 的簡單檔案。如果任何函式庫有循環匯入(例如,A 匯入 B,B 匯入 C,而 C 匯入 A),請考慮一起遷移這些函式庫。

若要手動遷移套件,請執行下列步驟

  1. 編輯套件的 pubspec.yaml 檔案,將最低 SDK 約束設定為至少 2.12.0

    yaml
    environment:
      sdk: '>=2.12.0 <3.0.0'
  2. 重新產生 套件組態檔

    $ dart pub get

    執行 dart pub get,且最低 SDK 約束至少為 2.12.0,會將套件中每個函式庫的預設語言版本設定為至少 2.12,讓它們全部選擇加入 Null 安全性。

  3. 在您的 IDE 中開啟套件。
    您可能會看到許多分析錯誤。這很正常。

  4. 使用分析器找出靜態錯誤,並遷移每個 Dart 檔案的程式碼。
    視需要,透過新增 ?!requiredlate 來消除靜態錯誤。

參閱 不健全的 Null 安全性,以取得更多手動遷移程式碼的說明。

3. 分析

#

更新您的套件(在您的 IDE 或命令列中使用 dart pub get)。然後使用您的 IDE 或命令列對您的程式碼執行 靜態分析

$ dart pub get
$ dart analyze     # or `flutter analyze`

4. 測試

#

如果您的程式碼通過分析,請執行測試

$ dart test       # or `flutter test`

您可能需要更新會產生 Null 值的測試。

如果您需要對程式碼進行大幅度變更,則可能需要重新遷移程式碼。如果是這樣,請在再次使用遷移工具之前,還原您的程式碼變更。

5. 發布

#

我們建議您在遷移後立即發布套件(可能是預發布版本)

更新套件版本

#

更新套件版本以表示重大變更

  • 如果您的套件已經達到 1.0.0 或更高版本,請增加主版本。例如,如果前一個版本是 2.3.2,則新版本為 3.0.0

  • 如果您的套件尚未達到 1.0.0,請增加次要版本將版本更新為 1.0.0。例如,如果前一個版本是 0.3.2,則新版本為 0.4.01.0.0

檢查 pubspec

#

在您發布套件的穩定 Null 安全性版本之前,我們強烈建議您遵循下列 pubspec 規則

  • 將 Dart 最低 SDK 約束設定為您測試過的最低穩定版本(至少 2.12.0)。
  • 使用所有直接依賴關係的穩定版本。

歡迎使用 Null 安全性

#

如果您已經進行到這個步驟,您應該已經擁有完全遷移的 Null 安全性 Dart 套件。

如果您依賴的所有套件也已遷移,則您的程式在 Null 參考錯誤方面是健全的。在執行或編譯您的程式碼時,您應該會看到類似這樣的輸出

Compiling with sound null safety

來自所有 Dart 團隊的感謝,感謝您遷移您的程式碼。