Flutter项目迁移到Null Safety
相关文章:
- 创建分支命名为
flutter2_null-safety
,并切换到新分支。 - 项目中使用了
fvm
,执行fvm use stable
,使用Flutter
最新的stable
分支。 - 执行
flutter doctor
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.2.3, on macOS 11.5.1 20G80 darwin-x64, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] Connected device (2 available)
• No issues found!
- 查看
dart
版本,是否为2.12
或更高
$ dart --version
fvm: running Dart from Flutter "stable"
Dart SDK version: 2.13.4 (stable) (Wed Jun 23 13:08:41 2021 +0200) on "macos_x64"
- 检查所有依赖的迁移状态
$ dart pub outdated --mode=null-safety
fvm: running Dart from Flutter "stable"
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
[✓] indicates versions opting in to null safety.
Package Name Current Upgradable Resolvable Latest
direct dependencies:
amap_location ✗0.2.0 (git) - - ✗0.2.0 (git)
audioplayers ✗0.17.4 (git) - - ✗0.17.4 (git)
azlistview ✗0.1.2 - - ✓2.0.0-nullsafety.0
badges ✗1.2.0 - - ✓2.0.1
barcode_scan ✗2.0.2 - - ✗3.0.1
cached_network_image ✗2.5.1 - - ✓3.1.0
chewie ✗0.12.2 - - ✓1.2.2
connectivity ✗2.0.2 - - ✓3.0.6
date_range_picker ✗1.0.7 - - ✗1.0.7
device_info ✗1.0.0 - - ✓2.0.2
dio ✗3.0.10 - - ✓4.0.0
event_bus ✗1.1.1 - - ✓2.0.0
exifdart ✗0.7.0+3 - - ✓0.8.0-dev.2
fdottedline ✗1.0.1 - - ✗1.0.1
flutter_app_badger ✗1.1.2 - - ✓1.2.0
...
...
...
dev_dependencies:
build_runner ✗1.11.1 - - ✓2.0.6
No resolution was found. Try running `dart pub upgrade --null-safety --dry-run` to explore why.
-
依赖迁移优先级
A依赖B,B依赖C,迁移顺序为:C > B > A。 -
对本地引入的库分析是否具备迁移条件
① 几个自己定义的插件库库已经创建了null-safety
分支做了迁移支持。
② 其他三方的库也都找到了可替换了null-safety
库。
③ 本地引入的插件,替换为git方式引入,创建null-safety
分支,做迁移支持。
以上所有插件,保证都具备迁移条件。
如果插件还没迁移,使用以下第⑧条的方法先将插件迁移,迁移完之后,使用null-safety
分支。
talkingdata_appanalytics_plugin:
git:
url: http://*******/*******/app_analytics_sdk_flutter.git
ref: null-safety
- 开始迁移
①fvm use stable
②dart --version
确保使用的dart为最新版本
③ 运行dart pub outdated --mode=null-safety
以确保所有依赖为最新且空安全。
$ dart pub outdated --mode=null-safety
fvm: running Dart from Flutter "stable"
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
[✓] indicates versions opting in to null safety.
All your dependencies declare support for null-safety.
如果依赖没有更新到最新版本,比如以下:
$ dart pub outdated --mode=null-safety
fvm: running Dart from Flutter "stable"
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
[✓] indicates versions opting in to null safety.
Package Name Current Upgradable Resolvable Latest
direct dependencies:
path_provider ✗1.6.22 - ✓2.0.2 ✓2.0.2
uuid ✗2.2.2 - ✓3.0.4 ✓3.0.4
dev_dependencies:
http ✗0.12.2 - ✓0.13.3 ✓0.13.3
No resolution was found. Try running `dart pub upgrade --null-safety --dry-run` to explore why.
3 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
运行 dart pub upgrade --null-safety
将依赖升级至支持空安全的最新版本。 注意: 该命令会更改你的 pubspec.yaml
文件。
④ 在包含 pubspec.yaml
的目录下,执行 dart migrate
命令,启动迁移工具。
$ dart migrate
fvm: running Dart from Flutter "stable"
Migrating /Users/yuanzhiying/Desktop/app_analytics_sdk_flutter
See https://dart.dev/go/null-safety-migration for a migration guide.
Note: more than one project found; migrating the top-level project.
Analyzing project...
No analysis issues found.
Generating migration suggestions...
Compiling instrumentation information...
View the migration suggestions by visiting:
http://127.0.0.1:52996/Users/yuanzhiying/Desktop/app_analytics_sdk_flutter?authToken=zbeBO82KY54%3D
Use this interactive web view to review, improve, or apply the results.
When finished with the preview, hit ctrl-c to terminate this process.
If you make edits outside of the web view (in your IDE), use the 'Rerun from
sources' action.
⑤ 访问http://127.0.0.1:52996/Users/yuanzhiying/Desktop/app_analytics_sdk_flutter?authToken=zbeBO82KY54%3D
浏览器打开,根据提示或具体情况处理代码。
工具给推荐了默认的处理方法,点击代码,可以看到右侧Proposed Edits
里有具体的说明。在迁移工具的 Edit Details
窗格中,你可以通过 Add /*?*/ hint
和 Add /*!*/ hint
按钮来添加提示标记。
按下这些按钮,相应的标记会立刻添加到代码中,并且 无法撤销。如果你想删除标记,可以和平常一样使用代码编辑器删除它。
就算迁移工具正在运行,你也可以使用编辑器添加提示标记。由于你的代码还未迁移到空安全,所以无法使用空安全的新特性。但是你可以进行与空安全无关的改动,例如重构。
当你完成编辑后,点击 Rerun from sources
进行更改。
⑥ 只进行部分文件的迁移
尽管我们希望你能一次性完成迁移工作,但对于大体量的应用或 package
而言并不是简单的事。如果你想只迁移部分文件,请将暂时不迁移的文件前方的绿色勾选框取消勾选。稍后应用迁移更改时,这些文件会加上 Dart 2.9
[版本注释][version comment],其他内容保持不变。
更多有关渐进迁移空安全的内容,请阅读 非健全的空安全。
⑦ 处理完之后,再次执行dart migrate
$ dart migrate
fvm: running Dart from Flutter "stable"
Migrating /Users/yuanzhiying/Desktop/app_analytics_sdk_flutter
See https://dart.dev/go/null-safety-migration for a migration guide.
Note: more than one project found; migrating the top-level project.
Analyzing project...
All sources appear to be already migrated. Nothing to do.
9、迁移完成
非健全的空安全
一个 Dart
程序可以同时包含已经是 空安全 和未迁移至空安全的库。这些 混合模式的程序 会运行在 非健全的空安全 下。
为了在保持与传统库运行时的兼容性的同时,能为健全的空安全程序提供健全性,Dart
工具提供了以下两种模式的支持:
- 以 非健全的空安全 运行的混合模式的程序。在运行时有可能出现
null
引用错误,但这只是因为一些null
值和可空类型在非空安全的库中污染了空安全的代码。 - 当程序完全迁移至空安全,且它所依赖的库 全部 都迁移完成后,它就在以 健全的空安全 运行,拥有所有由健全性带来的保证和编译优化。
逐步迁移
因为 Dart
支持混合模式的空安全,所以你可以一个个迁移你的库(通常是一个文件),同时能正常运行程序和测试。
我们推荐你 优先迁移最下层的库 —— 指的是没有导入其他包的库。接着迁移直接依赖了下层库的依赖库。最后再迁移依赖项最多的库。
举个例子,假设你的 lib/src/util.dart
导入了其他(空安全)的软件包和核心库,但它没有包含任何 import '<本地路径>'
的引用。那么你应当优先考虑迁移 util.dart
,然后迁移依赖了 util.dart
的文件。如果有一些循环引用的库(例如 A
引用了 B
,B
引用了 C
,C
引用了 A
),建议同时对它们进行迁移。
使用迁移工具
你可以使用 迁移工具 进行渐进迁移。如果你需要排除部分文件或文件夹,勾选绿色的勾选框。下方的截图中,bin
文件夹的所有文件都已被排除。
每个不迁移的文件都会加上 2.9
语言版本的注释。你可以之后再次运行 dart migrate
继续迁移。已迁移的文件将显示为禁用的勾选框,它们无法撤销迁移更改。
测试或运行混合版本的程序
想要测试或运行混合版本的代码,你需要禁用健全的空安全。有两种方式可以进行操作:
- 在
dart
和flutter
命令里,加入--no-sound-null-safety
标记禁用。例如:
$ dart --no-sound-null-safety run
$ flutter run --no-sound-null-safety
- 或者,设定程序入口的语言版本 —— 包含
main()
函数的文件 —— 设定为2.9
。在Flutter
应用中,一般是lib/main.dart
。在命令行应用中,一般是bin/<package 名称>.dart
。同时你也可以设定test
下的文件,因为它们也包含程序入口。例如
// @dart=2.9
import 'src/my_app.dart';
main() {
//...
}
以上两种方式的规避,对于 正在 增量迁移的过程非常有用,但这样做意味着你并未在完全启用空安全的情况下测试你的代码。当你完成增量迁移后,也请记得将测试代码 重新 迁移至空安全。