Dart 3 迁移指南
Dart 3 是一个主要版本,为 Dart 引入了新的核心功能:records、patterns 和 class modifiers。
除了这些新功能之外,Dart 3 还包含一些可能会破坏现有代码的变更。
本指南将帮助您解决升级到 Dart 3 后可能遇到的任何迁移问题。
介绍
#无版本控制变更与有版本控制变更
#下面列出的潜在破坏性变更分为两类
无版本控制变更:这些变更在升级到 Dart 3.0 SDK 或更高版本后会影响所有 Dart 代码。无法“关闭”这些变更。
有版本控制变更:这些变更仅在包或应用的语言版本设置为 >= Dart 3.0 时适用。语言版本源自
pubspec.yaml文件中sdk的下限约束。像这样的 SDK 约束 不 会应用 Dart 3 有版本控制的变更yamlenvironment: sdk: '>=2.14.0 <3.0.0'但像这样的 SDK 约束会应用
yamlenvironment: 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
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_overridedart 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.迁移
#将冒号用法改为
int someInt({int x: 0}) => x;使用等号
int someInt({int x = 0}) => x;此迁移可以手动完成,也可以使用 dart fix 自动完成
dart fix --apply --code=obsolete_colon_for_default_valuemixin
#在 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 来恢复到原始行为,这样它就不再被解释为模式
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):您可以使用 dart fix 或在您的 IDE 中运行快速修复此破坏性变更。
continue
#如果 continue 语句指向的标签不是循环(for、do 和 while 语句)或 switch 成员,Dart 3 将报告编译时错误。
范围
#这是有版本控制变更,仅适用于语言版本 3.0 或更高版本。
症状
#您将看到类似如下的错误
The label used in a 'continue' statement must be defined on either a loop or a switch member.迁移
#如果改变行为是可接受的,将 continue 更改为指向有效的带标签语句,该语句必须附加到 for、do 或 while 语句。
如果您想保留行为,将 continue 语句更改为 break 语句。在 Dart 的早期版本中,未指向循环或 switch 成员的 continue 语句行为类似于 break。
Dart 3 核心库变更
#删除的 API
#破坏性变更 #49529:核心库已清理,移除了已弃用多年的 API。以下 API 不再存在于 Dart 核心库中。
范围
#这是无版本控制变更,适用于所有 Dart 3 代码。
dart:core
#- 移除了已弃用的
List构造函数,因为它不是空安全的。使用列表字面量(例如空列表的[]或空类型化列表的<int>[])或List.filled。这仅影响非空安全代码,因为空安全代码已无法使用此构造函数。 - 移除了
int.parse、double.parse和num.parse上已弃用的onError参数。改用tryParse方法。 - 移除了已弃用的
proxy和Provisional注解。原始的proxy注解在 Dart 2 中没有效果,并且Provisional类型和provisional常量仅在 Dart 2.0 开发过程中内部使用。 - 移除了已弃用的
Deprecated.expiresgetter。改用Deprecated.message。 - 移除了已弃用的
CastError错误。改用TypeError。 - 移除了已弃用的
FallThroughError错误。之前抛出此错误的fall-through类型在 Dart 2.0 中已成为编译时错误。 - 移除了已弃用的
NullThrownError错误。空安全代码从不抛出此错误。 - 移除了已弃用的
AbstractClassInstantiationError错误。在 Dart 2.0 中调用抽象类的构造函数已成为编译时错误。 - 移除了已弃用的
CyclicInitializationError。在空安全代码中,循环依赖项不再在运行时检测。此类代码将以其他方式失败,可能出现 StackOverflowError。 - 移除了已弃用的
NoSuchMethodError默认构造函数。改用NoSuchMethodError.withInvocation命名构造函数。 - 移除了已弃用的
BidirectionalIterator类。现有的双向迭代器仍然可以工作,只是它们没有共享的超类型将其锁定在特定的向后移动名称上。
dart:async
#- 移除了已弃用的
DeferredLibrary类。改用deferred as导入语法。
dart:developer
#- 移除了已弃用的
MAX_USER_TAGS常量。改用maxUserTags。 - 移除了已弃用的
Metrics、Metric、Counter和Gauge类,因为它们自 Dart 2.0 起已损坏。
dart:html
#- 如先前宣布,
Document和HtmlDocument中已弃用的registerElement和registerElement2方法已被移除。详见 #49536。
dart:math
#Random接口只能实现,不能扩展。
dart:io
#- 更新
NetworkProfiling以适应 vm_service:11.0.0 中引入的新的Stringids
症状
#Dart 分析(例如在您的 IDE 中,或在 dart analyze/flutter analyze 中)将失败并出现类似如下错误
error line 2 • Undefined class 'CyclicInitializationError'.迁移
#手动迁移,停止使用这些 API。
Extends 与 implements
#Dart 3 支持新的类修饰符,可以限制类的能力。它们已应用于核心库中的许多类。
范围
#这是有版本控制变更,仅适用于语言版本 3.0 或更高版本。
dart:async
#以下声明只能实现,不能扩展
StreamConsumerStreamIteratorStreamTransformerMultiStreamController
这些声明都不包含任何可继承的实现。它们被标记为
interface,表示它们仅 intended 作为接口。
dart:core
#Function类型不能再被实现、扩展或混入。自 Dart 2.0 起,出于向后兼容性,允许编写implements Function,但它没有产生任何效果。在 Dart 3.0 中,Function类型是 final 的,不能被子类型化,防止代码错误地认为它有效。以下声明只能实现,不能扩展
ComparableExceptionIteratorPatternMatchRegExpRegExpMatchStackTraceStringSink
这些声明都不包含任何可继承的实现。它们被标记为
interface,表示它们仅 intended 作为接口。以下声明不能再被实现或扩展
MapEntryOutOfMemoryErrorStackOverflowErrorExpandoWeakReferenceFinalizer
MapEntry值类受到限制以启用后续优化。其余类与平台紧密耦合,不打算子类化或实现。
dart:collection
#以下接口不能再被扩展,只能被实现
Queue
以下实现类不能再被实现
LinkedListLinkedListEntry
以下实现类不能再被实现或扩展
HasNextIterator(也已弃用。)HashMapLinkedHashMapHashSetLinkedHashSetDoubleLinkedQueueListQueueSplayTreeMapSplayTreeSet
Dart 3 工具变更
#删除的工具
#从历史上看,Dart 团队提供了许多小型开发者工具,用于格式化代码 (dartfmt)、分析代码 (dartanalyzer) 等。在 Dart 2.10(2020 年 10 月)中,我们引入了一个新的统一的 Dart 开发者工具,即 dart 工具。
范围
#这是无版本控制变更,适用于所有 Dart 3 代码。
症状
#在 Dart 3 中,这些小型工具不再存在,已被新的组合 dart 工具取代。
迁移
#使用 dart 工具中可用的新子命令
| 历史工具 | dart 替代项 | 弃用 | 停用 |
|---|---|---|---|
stagehand | dart create | 2.14 | 2.14* |
dartfmt | dart format | 2.14 | 2.15 |
dart2native | dart compile exe | 2.14 | 2.15 |
dart2js | dart compile js | 2.17 | 2.18 |
dartdevc | webdev | 2.17 | 2.18 |
dartanalyzer | dart analyze | 2.16 | 2.18 |
dartdoc | dart doc | 2.16 | 2.17 |
pub | dart pub | 2.15 | 2.17 |
空安全迁移工具
#由于 Dart 3 不支持没有空安全的代码,以下空安全迁移命令已被移除
dart migratedart pub upgrade --null-safetydart 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.迁移
#替换分析器配置的这一部分
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false为
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 代码。