Dart 3 迁移指南
Dart 3 是一个主要版本,它为 Dart 引入了新的核心功能:记录、模式 和 类修饰符。
除了这些新功能之外,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_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.
迁移
#从使用冒号
int someInt({int x: 0}) => x;
更改为使用等号
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
。此限制适用于尝试将该类用作混入的任何库中的代码,无论后者的库语言版本如何。
范围
#这是一个 版本化更改,仅适用于 3.0 或更高版本的语言版本。
症状
#类似以下的分析错误
Mixin can only be applied to class.
当一个既不是 mixin class
也不是 mixin
的类在 with
子句中使用时,分析器会生成此诊断。
迁移
#确定该类是否打算用作混入。
如果该类定义了一个接口,请考虑使用 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.expires
获取器。请改用Deprecated.message
。 - 删除了已弃用的
CastError
错误。请改用TypeError
。 - 删除了已弃用的
FallThroughError
错误。在 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 中引入的新String
ID。
症状
#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
以表示它们仅旨在用作接口。
dart:core
#Function
类型不再可以实现、扩展或混合使用。自 Dart 2.0 以来,编写implements Function
已允许用于向后兼容,但它没有任何效果。在 Dart 3.0 中,Function
类型是最终的,不能进行子类型化,从而防止代码错误地假设它有效。以下声明只能实现,不能扩展
Comparable
Exception
Iterator
Pattern
Match
RegExp
RegExpMatch
StackTrace
StringSink
这些声明中没有任何一个包含要继承的实现。它们被标记为
interface
以表示它们仅旨在用作接口。以下声明不再可以实现或扩展
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 替换 | 弃用 | 停止使用 |
---|---|---|---|
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 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.
迁移
#将分析器配置的这部分
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 代码。
除非另有说明,否则本网站上的文档反映的是 Dart 3.5.3。页面上次更新于 2024-04-11。 查看源代码 或 报告问题。