跳至主要內容

遷移至 Null 安全性

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

  1. 等待您相依的套件完成遷移。
  2. 遷移您套件的程式碼,最好使用互動式遷移工具。
  3. 靜態分析您套件的程式碼。
  4. 測試以確保您的變更有效。
  5. 如果套件已在 pub.dev 上,發布 Null 安全性版本作為預發布版本。

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


如何將 Dart 套件遷移至 Null 安全性

1. 等待遷移

#

我們強烈建議依序遷移程式碼,先遷移相依性圖的葉節點。例如,如果套件 C 相依於套件 B,而套件 B 相依於套件 A,則應先將 A 遷移至 Null 安全性,然後是 B,最後是 C。

Illustration of C/B/A sentence

雖然您可以在您的相依性支援 Null 安全性之前遷移,但當您的相依性遷移時,您可能需要變更您的程式碼。例如,如果您預測函數將採用可為 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

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

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

Output of dart pub outdated

輸出顯示,套件的所有相依性都有可解析的預發布版本,這些版本支援 Null 安全性。

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

更新相依性

#

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

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

  2. 執行 dart pub get

2. 遷移

#

您的程式碼需要成為 Null 安全性的多數變更都是容易預測的。例如,如果變數可以為 null其類型需要 ? 字尾。如果具名參數不應為可 Null 的,請將其標記為 required 或給它一個預設值

您有兩種遷移選項

使用遷移工具

#

遷移工具會取得一個 Null 不安全的 Dart 程式碼套件,並將其轉換為 Null 安全性。您可以透過將提示標記新增至您的 Dart 程式碼來引導工具的轉換。

在啟動工具之前,請確保您已準備就緒

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

在包含套件 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

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

瞭解遷移結果

#

若要查看每個變更 (或未變更) 的原因,請在 Proposed Edits 窗格中按一下其行號。原因會顯示在 Edit Details 窗格中。

例如,考慮以下來自 Null 安全性之前的程式碼

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];

透過按一下 line 3 連結,您可以查看遷移工具新增 ! 的原因。因為您知道 zero 不可能為 Null,所以您可以改善遷移結果。

改善遷移結果

#

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

  • 在遷移工具的 Edit Details 窗格中,您可以使用 Add /*?*/ hintAdd /*!*/ hint 按鈕來插入提示標記。

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

  • 即使工具仍在執行,您也可以使用編輯器來新增提示標記。因為您的程式碼尚未選擇加入 Null 安全性,所以您無法使用新的 Null 安全性功能。但是,您可以進行重構等不相依於 Null 安全性功能的變更。

    當您完成編輯程式碼時,請按一下 Rerun from sources 以挑選您的變更。

下表顯示您可以用來變更遷移工具建議編輯的提示標記。

提示標記對遷移工具的影響
expression /!/在遷移後的程式碼中新增 !,將 expression 轉換為其基礎的不可為 Null 類型。
type /!/type 標記為不可為 Null。
/*?*/將前面的類型標記為可為 Null。
/*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 版本註解

如需有關增量遷移的詳細資訊,請參閱不健全的 Null 安全性

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

套用變更

#

當您喜歡遷移工具建議的所有變更時,請按一下 Apply migration。遷移工具會刪除提示標記並儲存遷移後的程式碼。該工具也會更新 pubspec 中的最小 SDK 約束,這會使套件選擇加入 Null 安全性。

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

手動遷移

#

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

我們建議您先遷移葉程式庫—不從套件匯入其他檔案的程式庫。然後遷移直接相依於葉程式庫的程式庫。最後遷移具有最多套件內相依性的程式庫。

例如,假設您有一個 lib/src/util.dart 檔案,它匯入其他 (Null 安全性) 套件和核心程式庫,但不具有任何 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

    使用至少 2.12.0 的較低 SDK 約束執行 dart pub get,會將套件中每個程式庫的預設語言版本設定為至少 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 團隊全體成員感謝您遷移您的程式碼。