跳到主內容

Dart 3 遷移指南

Dart 3 是一個主要版本,為 Dart 引入了新的核心功能:recordspatternsclass modifiers

除了這些新功能之外,Dart 3 還包含一些可能會破壞現有程式碼的變更。

本指南將幫助您解決升級到 Dart 3 後可能遇到的任何遷移問題。

介紹

#

無版本控制變更與有版本控制變更

#

下面列出的潛在破壞性變更分為兩類

  • 無版本控制變更:這些變更在升級到 Dart 3.0 SDK 或更高版本後會影響所有 Dart 程式碼。無法“關閉”這些變更。

  • 有版本控制變更:這些變更僅在包或應用的語言版本設定為 >= Dart 3.0 時適用。語言版本源自 pubspec.yaml 檔案sdk 的下限約束。像這樣的 SDK 約束 會應用 Dart 3 有版本控制的變更

    yaml
    environment:
      sdk: '>=2.14.0 <3.0.0'

    但像這樣的 SDK 約束會應用

    yaml
    environment:
      sdk: '>=3.0.0 <4.0.0'

要使用新的 Dart 3 功能,您必須將語言版本更新到 3.0。同時您也將獲得 Dart 3 有版本控制的變更。

Dart 3 向後相容性

#

許多使用 Dart 2.12 或更高版本實現空安全的包和應用很可能與 Dart 3 向後相容。對於任何 SDK 約束的下限為 2.12.0 或更高的包,這都是可能的。

Dart 的 pub 工具允許即使上限限制為低於 3.0.0 的版本也能解析。例如,具有以下約束的包將允許使用 Dart 3.x SDK 解析,因為當低約束為 2.12 或更高時,pub 會將上限約束 <3.0.0 重新解釋為 <4.0.0

yaml
environment:
  sdk: '>=2.14.0 <3.0.0'           # This is interpreted as '>=2.14.0 <4.0.0'

這使得開發者可以使用 Dart 3 健全的空安全與已經支援 2.12 空安全的包一起工作,而無需第二次遷移,除非程式碼受到其他任何 Dart 3 變更的影響。

測試影響

#

要了解您的原始碼是否受到任何 Dart 3 變更的影響,請使用以下步驟

dart --version    # Make sure this reports 3.0.0 or higher.
dart pub get      # This should resolve without issues.
dart analyze      # This should pass without errors.

如果 pub get 步驟失敗,請嘗試升級您的依賴項,看看是否有更新的版本可能支援 Dart 3

dart pub upgrade
dart analyze      # This should pass without errors.

或者,如果需要,也包括 主要版本 的升級

dart pub upgrade --major-versions
dart analyze      # This should pass without errors.

Dart 3 語言變更

#

100% 健全的空安全

#

Dart 2.12 在兩年多前引入了空安全。在 Dart 2.12 中,使用者需要透過 pubspec 設定啟用空安全。在 Dart 3 中,空安全是內建的;您無法將其關閉。

範圍

#

這是無版本控制變更,適用於所有 Dart 3 程式碼。

症狀

#

未開發支援空安全的包在使用 pub get 解析依賴項時會引起問題

dart pub get

Because pkg1 doesn't support null safety, version solving failed.
The lower bound of "sdk: '>=2.9.0 <3.0.0'" must be 2.12.0 or higher to enable null safety.

使用語言版本註釋選擇低於 2.12 任何語言版本而選擇不使用空安全的庫將導致分析或編譯錯誤

dart analyze .
Analyzing ....                         0.6s

  error • lib/pkg1.dart:1:1 • The language version must be >=2.12.0. 
  Try removing the language version override and migrating the code.
  • illegal_language_version_override
dart run bin/my_app.dart
../pkg1/lib/pkg1.dart:1:1: Error: Library doesn't support null safety.
// @dart=2.9
^^^^^^^^^^^^

遷移

#

在開始任何 Dart 3 遷移之前,請確保您的應用或包已 100% 遷移以啟用空安全。這需要 Dart 2.19 SDK,而不是 Dart 3 SDK。要了解如何首先將您的應用或包遷移以支援空安全,請查閱空安全遷移指南

預設值的冒號語法

#

出於歷史原因,命名的可選引數可以使用 := 來指定其預設值。在 Dart 3 中,只允許使用 = 語法。

範圍

#

這是有版本控制變更,僅適用於語言版本 3.0 或更高版本。

症狀

#

Dart 分析會產生類似如下錯誤

line 2 • Using a colon as a separator before a default value is no longer supported.

遷移

#

將冒號用法改為

dart
int someInt({int x: 0}) => x;

使用等號

dart
int someInt({int x = 0}) => x;

此遷移可以手動完成,也可以使用 dart fix 自動完成

dart fix --apply --code=obsolete_colon_for_default_value

mixin

#

在 Dart 3 之前,任何 class 都可以用作 mixin,只要它沒有宣告的建構函式,並且除了 Object 之外沒有超類。

在 Dart 3 中,語言版本 3.0 或更高版本庫中宣告的類除非標記為 mixin,否則不能用作 mixins。此限制適用於任何嘗試將該類用作 mixin 的庫中的程式碼,而不管後者的語言版本如何。

範圍

#

這是有版本控制變更,僅適用於語言版本 3.0 或更高版本。

症狀

#

類似如下的分析錯誤

Mixin can only be applied to class.

當一個既不是 mixin class 也不是 mixin 的類用於 with 子句時,分析器會生成此診斷資訊。

遷移

#

確定該類是否打算用作 mixin。

如果該類定義了一個介面,請考慮使用 implements

switch

#

Dart 3.0 將 switch case 解釋為 模式 而不是常量表達式。

範圍

#

這是有版本控制變更,僅適用於語言版本 3.0 或更高版本。

症狀

#

switch case 中找到的大多數常量表達式都是具有相同含義的有效模式(命名常量、字面量等)。這些將行為相同,不會出現任何症狀。

少數不是有效模式的常量表達式將觸發 invalid_case_patterns lint

遷移

#

您可以透過在 case 模式前加上 const 來恢復到原始行為,這樣它就不再被解釋為模式

dart
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):

您可以使用 dart fix 或在您的 IDE 中執行快速修復此破壞性變更。

continue

#

如果 continue 語句指向的標籤不是迴圈(fordowhile 語句)或 switch 成員,Dart 3 將報告編譯時錯誤。

範圍

#

這是有版本控制變更,僅適用於語言版本 3.0 或更高版本。

症狀

#

您將看到類似如下的錯誤

The label used in a 'continue' statement must be defined on either a loop or a switch member.

遷移

#

如果改變行為是可接受的,將 continue 更改為指向有效的帶標籤語句,該語句必須附加到 fordowhile 語句。

如果您想保留行為,將 continue 語句更改為 break 語句。在 Dart 的早期版本中,未指向迴圈或 switch 成員的 continue 語句行為類似於 break

Dart 3 核心庫變更

#

刪除的 API

#

破壞性變更 #49529:核心庫已清理,移除了已棄用多年的 API。以下 API 不再存在於 Dart 核心庫中。

範圍

#

這是無版本控制變更,適用於所有 Dart 3 程式碼。

dart:core

#
  • 移除了已棄用的 List 建構函式,因為它不是空安全的。使用列表字面量(例如空列表的 [] 或空型別化列表的 <int>[])或 List.filled。這僅影響非空安全程式碼,因為空安全程式碼已無法使用此建構函式。
  • 移除了 int.parsedouble.parsenum.parse 上已棄用的 onError 引數。改用 tryParse 方法。
  • 移除了已棄用的 proxyProvisional 註解。原始的 proxy 註解在 Dart 2 中沒有效果,並且 Provisional 型別和 provisional 常量僅在 Dart 2.0 開發過程中內部使用。
  • 移除了已棄用的 Deprecated.expires getter。改用 Deprecated.message
  • 移除了已棄用的 CastError 錯誤。改用 TypeError
  • 移除了已棄用的 FallThroughError 錯誤。之前丟擲此錯誤的fall-through型別在 Dart 2.0 中已成為編譯時錯誤。
  • 移除了已棄用的 NullThrownError 錯誤。空安全程式碼從不丟擲此錯誤。
  • 移除了已棄用的 AbstractClassInstantiationError 錯誤。在 Dart 2.0 中呼叫抽象類的建構函式已成為編譯時錯誤。
  • 移除了已棄用的 CyclicInitializationError。在空安全程式碼中,迴圈依賴項不再在執行時檢測。此類程式碼將以其他方式失敗,可能出現 StackOverflowError。
  • 移除了已棄用的 NoSuchMethodError 預設建構函式。改用 NoSuchMethodError.withInvocation 命名建構函式。
  • 移除了已棄用的 BidirectionalIterator 類。現有的雙向迭代器仍然可以工作,只是它們沒有共享的超型別將其鎖定在特定的向後移動名稱上。

dart:async

#

dart:developer

#

dart:html

#
  • 如先前宣佈,DocumentHtmlDocument 中已棄用的 registerElementregisterElement2 方法已被移除。詳見 #49536

dart:math

#
  • Random 介面只能實現,不能擴充套件。

dart:io

#
  • 更新 NetworkProfiling 以適應 vm_service:11.0.0 中引入的新的 String ids

症狀

#

Dart 分析(例如在您的 IDE 中,或在 dart analyze/flutter analyze 中)將失敗並出現類似如下錯誤

error line 2 • Undefined class 'CyclicInitializationError'.

遷移

#

手動遷移,停止使用這些 API。

Extends 與 implements

#

Dart 3 支援新的類修飾符,可以限制類的能力。它們已應用於核心庫中的許多類。

範圍

#

這是有版本控制變更,僅適用於語言版本 3.0 或更高版本。

dart:async

#
  • 以下宣告只能實現,不能擴充套件

    • StreamConsumer
    • StreamIterator
    • StreamTransformer
    • MultiStreamController

    這些宣告都不包含任何可繼承的實現。它們被標記為 interface,表示它們僅 intended 作為介面。

dart:core

#
  • Function 型別不能再被實現、擴充套件或混入。自 Dart 2.0 起,出於向後相容性,允許編寫 implements Function,但它沒有產生任何效果。在 Dart 3.0 中,Function 型別是 final 的,不能被子型別化,防止程式碼錯誤地認為它有效。

  • 以下宣告只能實現,不能擴充套件

    • Comparable
    • Exception
    • Iterator
    • Pattern
    • Match
    • RegExp
    • RegExpMatch
    • StackTrace
    • StringSink

    這些宣告都不包含任何可繼承的實現。它們被標記為 interface,表示它們僅 intended 作為介面。

  • 以下宣告不能再被實現或擴充套件

    • MapEntry
    • OutOfMemoryError
    • StackOverflowError
    • Expando
    • WeakReference
    • Finalizer

    MapEntry 值類受到限制以啟用後續最佳化。其餘類與平臺緊密耦合,不打運算元類化或實現。

dart:collection

#
  • 以下介面不能再被擴充套件,只能被實現

    • Queue
  • 以下實現類不能再被實現

    • LinkedList
    • LinkedListEntry
  • 以下實現類不能再被實現或擴充套件

    • HasNextIterator(也已棄用。)
    • HashMap
    • LinkedHashMap
    • HashSet
    • LinkedHashSet
    • DoubleLinkedQueue
    • ListQueue
    • SplayTreeMap
    • SplayTreeSet

Dart 3 工具變更

#

刪除的工具

#

從歷史上看,Dart 團隊提供了許多小型開發者工具,用於格式化程式碼 (dartfmt)、分析程式碼 (dartanalyzer) 等。在 Dart 2.10(2020 年 10 月)中,我們引入了一個新的統一的 Dart 開發者工具,即 dart 工具

範圍

#

這是無版本控制變更,適用於所有 Dart 3 程式碼。

症狀

#

在 Dart 3 中,這些小型工具不再存在,已被新的組合 dart 工具取代。

遷移

#

使用 dart 工具中可用的新子命令

歷史工具dart 替代項棄用停用
stagehanddart create2.142.14*
dartfmtdart format2.142.15
dart2nativedart compile exe2.142.15
dart2jsdart compile js2.172.18
dartdevcwebdev2.172.18
dartanalyzerdart analyze2.162.18
dartdocdart doc2.162.17
pubdart pub2.152.17

空安全遷移工具

#

由於 Dart 3 不支援沒有空安全的程式碼,以下空安全遷移命令已被移除

  • dart migrate
  • dart pub upgrade --null-safety
  • dart pub outdated --mode=null-safety

範圍

#

這是無版本控制變更,適用於所有 Dart 3 程式碼。

症狀

#

這些命令將失敗。

遷移

#

使用 Dart 2.19 遷移到空安全

分析器配置

#

分析器配置選項 中用於啟用更嚴格檢查的部分已更改。

範圍

#

這是無版本控制變更,適用於所有 Dart 3 程式碼。

症狀

#

以前的配置選項將失敗並出現類似如下警告

The option 'implicit-casts' is no longer supported.
Try using the new 'strict-casts' option.

遷移

#

替換分析器配置的這一部分

yaml
analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

yaml
analyzer:
  language:
    strict-casts: true
    strict-raw-types: true

其他工具變更

#
  • 已棄用的 Observatory 已預設隱藏。我們推薦使用 DevTools
  • 命令 dart format fix 已被 dart fix 取代 #1153
  • SDK 中捆綁的 Dart Web 編譯器快照檔案已清理 #50700
  • dart format 的輸出對於某些程式碼略有變化。
  • 結束對 Windows 上舊的 pub-cache 位置的向後相容性。在 Dart 3 之前,%APPDATA%\Pub\Cache 是 pub-cache 的備用位置。從 Dart 3 開始,預設的 pub-cache 位置是 %LOCALAPPDATA%\Pub\Cache。如果您已將全域性啟用的包新增到 PATH 中,請考慮更新 PATH 以包含 %LOCALAPPDATA%\Pub\Cache\bin

範圍

#

這是無版本控制變更,適用於所有 Dart 3 程式碼。