內容

不健全的 Null 安全性

Dart 程式可能包含一些 null 安全 的函式庫,也可能包含一些不是 null 安全的函式庫。這些混合版本程式仰賴不健全的 null 安全性

混合 語言版本 的能力讓套件維護人員可以移轉他們的程式碼,並知道即使是舊版使用者也能獲得新的錯誤修正和其他改善。然而,混合版本程式無法獲得 null 安全性帶來的所有優點。

此頁面說明健全和不健全 null 安全性之間的差異,目標是協助您決定何時移轉至 null 安全性。在概念性討論後,會提供逐步移轉的說明,接著說明如何測試和執行混合版本程式。

有聲和無聲的 Null 安全

#

Dart 透過結合靜態和執行時期檢查,提供健全的 null 安全性。每個選擇加入 null 安全性的 Dart 函式庫都會獲得所有靜態檢查,以及更嚴格的編譯時期錯誤。即使在包含非 null 安全函式庫的混合版本程式中,也是如此。只要您開始將部分程式碼移轉至 null 安全性,您就會開始獲得這些好處。

然而,混合版本程式無法擁有完全 null 安全應用程式所具有的執行時期健全保證。null 有可能從非 null 安全函式庫外洩至 null 安全程式碼,因為防止這種情況會破壞未移轉程式碼的現有行為。

為了在提供健全性給完全 null 安全程式的同時,維持與舊版函式庫的執行時期相容性,Dart 工具支援兩種模式

  • 混合版本程式以不健全的 null 安全性執行。null 參考錯誤有可能在執行時期發生,但僅是因為 null 或可為 null 的類型從某些非 null 安全函式庫中外洩並進入 null 安全程式碼。

  • 當程式完全移轉且所有函式庫都是 null 安全時,它就會以健全的 null 安全性執行,並具備健全性所啟用的所有保證和編譯器最佳化。

健全的 null 安全性是您可能想要達到的目標。如果程式的程式碼進入點函式庫已選擇加入 null 安全性,Dart 工具會自動以健全模式執行您的程式。如果您匯入非 null 安全函式庫,這些工具會印出警告,讓您知道它們只能以不健全的 null 安全性執行。

漸進式遷移

#

由於 Dart 支援混合版本程式,您可以一次移轉一個函式庫(通常是一個 Dart 檔案),同時仍然能夠執行您的程式及其測試。

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

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

使用遷移工具

#

您可以使用 移轉工具 逐步移轉。若要取消選擇檔案或目錄,請按一下綠色核取方塊。在以下螢幕截圖中,bin 目錄中的所有檔案都已取消選擇。

Screenshot of file viewer in migration tool

每個選擇退出的檔案都將保持不變,只會新增 2.9 語言版本註解。稍後您可以再次執行 dart migrate 以繼續遷移。任何已遷移的檔案都會顯示已停用的核取方塊:檔案一旦遷移,您就無法取消遷移。

手動遷移

#

如果您想要手動逐步遷移套件,請遵循以下步驟

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

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

    $ dart pub get

    使用較低的 SDK 約束 2.12.0 執行 dart pub get 會將套件中每個函式庫的預設語言版本設定為 2.12,讓它們全部加入空值安全性。

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

  4. 在您不希望在目前遷移過程中考量的任何 Dart 檔案頂端,新增 語言版本註解

    dart
    // @dart=2.9

    對位於 2.12 套件中的函式庫使用語言版本 2.9,可以減少來自未遷移程式碼的分析錯誤(紅色波浪線)。不過,不健全的空值安全性會減少分析器可以使用的資訊。例如,分析器可能會假設參數類型是非空值,即使 2.9 檔案可能會傳入空值。

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

測試或執行混合版本程式

#

若要測試或執行混合版本程式碼,您需要停用健全的空值安全性。您可以透過兩種方式執行此操作

  • 使用 --no-sound-null-safety 旗標停用 dartflutter 指令的健全空值安全性

    $ dart --no-sound-null-safety run
    $ flutter run --no-sound-null-safety
  • 或者,將進入點(包含 main() 函式的檔案)中的語言版本設定為 2.9。在 Flutter 應用程式中,此檔案通常命名為 lib/main.dart。在命令列應用程式中,此檔案通常命名為 bin/<packageName>.dart。您也可以選擇退出 test 底下的檔案,因為它們也是進入點。範例

    dart
    // @dart=2.9
    import 'src/my_app.dart';
    
    void main() {
      //...
    }

在逐步遷移過程中,使用這兩種機制之一選擇退出測試可能會對測試有所幫助,但這麼做表示您並未在啟用完整空值安全性的情況下測試您的程式碼。在完成函式庫的逐步遷移後,讓您的測試重新選擇加入空值安全性非常重要。