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.
当在 with
子句中使用既不是 mixin class
也不是 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.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
#- 移除了已弃用的
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
类型是 final 的,不能被子类型化,从而防止代码错误地假设它可以工作。以下声明只能被实现,而不能被扩展
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.6.0。页面最后更新于 2024-12-10。 查看源代码 或 报告问题。