原文地址:blog.codemagic.io/dart-null-s…
原文作者:medium.com/@sbis1999
发布时间:2021年1月18日
本Dart null安全指南主要是针对包作者的。虽然迁移一个应用程序需要几乎相同的步骤,但你应该考虑等到null safety在Dart的稳定版本中才进行迁移。
Dart在BETA中支持健全的null安全。
这篇文章是参考官方的迁移指南而写的,可以在这里找到。
由于null safety目前还在测试版中,并且即将准备稳定版的发布,所以对于包主来说,现在是试用它并准备迁移的最佳时机。让我们来看看在进行Dart null safety之前,你应该记住的一些事情。
本文作者:Souvik Biswas
需要注意的事项
FIRST,建议按顺序迁移代码。也就是说,如果你的包C对B有依赖,而B又对A有依赖,那就等A被迁移到null safety,然后是B,再开始迁移你的包C。
Dart空安全推荐迁移顺序
但是,如果,A已经迁移到了null safety,但是B还没有迁移,怎么办?如果你不想等B迁移,而是想把你的包C迁移到null safety,你也可以这样做。
在这种情况下,你不会得到null safety的所有优点,它将以一种null safety不健全。
第二,你至少要在Flutter的2.12 beta版本上才能使用null safety的包。另外,更新你的pubspec.yaml中的依赖关系到他们的null-safe版本(如果他们存在的话),以获得健全的null安全的优势。
第三,Dart提供了一个方便的迁移工具,可以帮助你将空安全引入到你的Dart代码中。在工具执行自动迁移过程后,它会高亮显示代码中被修改的部分,你可以在最后批准之前插入任何手动修改。
第四,不要忘记使用Dart分析工具对你的代码进行静态分析,这有助于确定你的代码是否符合风格准则,还可以指出任何可能被忽视的小bug。
第五,在迁移的代码上运行你的测试。如果它们中的任何一个都期待空值,那么你可能需要相应地更新测试。
第六,最后一步是发布你的包,但在此之前,确保你的pubspec.yaml文件中的最小SDK约束是2.12或更高。另外,更新你的包的版本,并加入nullsafety后缀。
现在,我将演示如何将一个dart包(目前没有null safety)迁移到null safety。
概述
我有一个小的Dart包,叫做morse_translator,它可以帮助加密和解密字符串到摩尔斯码,反之亦然。它使用了一个基于自定义的模式,支持所有小写英文字母和特殊字符。
我有一个小的Dart包,叫做morse_translator,它可以帮助加密和解密字符串到摩尔斯码,反之亦然。它使用了基于国际摩斯码标准的自定义模式,支持所有小写英文字母字符和特殊字符。
以下是对该库的一些见解。
class Morse {
int textLength;
int morseLength;
String text;
String morse;
Morse({
this.textLength,
this.morseLength,
this.text,
this.morse,
});
factory Morse.fromString(String normalText) {}
factory Morse.toString(String morseText) {}
}
它使用fromString和toString工厂方法将字符串转换为莫尔斯码。
这个库可以这样调用。
void main(List<String> arguments) {
try {
final m = Morse.fromString(testString);
print('Text: ${m.text}, length: ${m.textLength}');
print('Morse: ${m.morse}, length: ${m.morseLength}');
} catch (ArgumentError) {
print('Invalid input string: cannot be parsed');
}
}
const testString = 'hello world';
目前,该库没有空值安全机制。所以,我们将引入空值安全功能。
准备工作
在开始迁移过程之前,首先要切换到最新的Dart测试版。
你可以使用 brew 软件包管理器在 macOS 上切换到 Dart 测试版,如下所示。
brew unlink dart
brew install dart-beta
如果你使用的是Windows或Linux系统,请查看此页面。
我目前使用的Dart版本。
Dart SDK version: 2.12.0-133.2.beta (beta) (Tue Dec 15 09:55:09 2020 +0100)
如果你正在使用Flutter包,那么你可以通过使用以下方法切换到Flutter的最新测试版。
flutter channel beta flutter upgrade
该软件包包含以下依赖项。
dependencies:
characters: ^1.0.0
dev_dependencies:
test: ^1.15.7
正如我前面提到的,在迁移我们的软件包之前,我们应该首先检查依赖的null-safe版本是否可用。
你可以使用这个命令来检查。
dart pub outdated --mode=null-safety
我们所有依赖的空安全版本都是可用的,所以我们可以像这样用空安全更新到当前版本。
dependencies:
characters: ^1.1.0-nullsafety.5
dev_dependencies:
test: ^1.16.0-nullsafety.13
然后运行。
dart pub upgrade
代码迁移
现在您已经准备好将您的代码迁移到空安全状态。使代码成为空值安全的大部分改动都是容易预测的,所以最好的方法是使用dart迁移工具。
在运行迁移工具之前,先看看我的pubspec.yaml,它看起来像这样。
name: morse
description: A dart library for morse encryption and decryption
version: 1.0.0
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
characters: ^1.1.0-nullsafety.5
dev_dependencies:
test: ^1.16.0-nullsafety.13
你会注意到我仍然没有更新Dart SDK的版本到2.12或以上,因为迁移工具会自动为你更新。
运行迁移过程。
dart migrate
它将生成一个链接,你可以去查看它所提出的修改。你也可以通过使用链接的DartPad或者直接从你的IDE中点击DartPad上的RERUN FROM SOURCES来手动执行任何进一步的修改。
在我的例子中,打开链接后,建议做如下修改。
建议的修改
但在这里,我不希望这些是可空的。所以我可以点击一个"?"。在右边一栏,你会看到一些与提议的更改有关的细节。
拟议变动
在这里,你可以点击Add /*!*/提示,使其不可空。然后,点击 "RERUN WITH CHANGES"--这将应用更改并更新所有与之相关的代码。
这将使那些字段成为required字段,使其不可空。
另外,我在 fromString 和 toString 工厂方法中进行了一些空检查,并抛出了一个 ArgumentError。
你可以删除这些不必要的空检查。
最后,点击APPLY MIGRATION来接受所有的改变。
Dart null安全迁移指南。点击 "应用迁移"
应用后,如果你去pubspec.yaml文件,你会发现它也更新了Dart SDK版本。
environment:
sdk: '>=2.12.0-133.2.beta <3.0.0'
测试和分析
现在你已经成功地迁移到了声音无效模式,你应该检查你的测试是否成功运行。
我之前的morse_test.dart文件包含了两个空测试。
void main() {
test('Text: Fails with null', () {
expect(() => Morse.fromString(null), throwsArgumentError);
});
test('Morse: Fails with null', () {
expect(() => Morse.toString(null), throwsArgumentError);
});
// ...
}
然而,我们不需要再测试这些了,因为它们现在甚至不接受null,并且会在编译过程中抛出一个错误。所以,删除所有对null的测试。
使用以下方法运行这些测试
dart test # or `flutter test`
对你的代码进行静态分析,以确保你遵循正确的风格准则,并防止错误。
dart analyze # or `flutter analyze`
发布
最后,你必须更新软件包的版本,并加入nullsafety后缀,如下所示。
version: 1.1.0-nullsafety.0
用新的变化更新CHANGELOG.md文件。
执行一次干运行来检查 pub publish 的工作情况。
pub publish --dry-run
当你准备好发布你的软件包时,使用以下命令。
pub publish
使用Codemagic实现自动化
你可以通过使用Codemagic来自动化Dart包的测试和发布阶段。
按照以下步骤进行。
-
进入Codemagic仪表板。
-
搜索你的项目,然后点击设置构建。
- 选择Flutter/Dart包。
- 下载
codemagic.yaml文件。
- 修改YAML文件如下。
workflows:
flutter-package:
name: morse_translator
environment:
vars:
CREDENTIALS: Encrypted(...)
flutter: beta
cache:
cache_paths:
- $FLUTTER_ROOT/.pub-cache
scripts:
- name: Switch to Dart beta
script: |
brew unlink dart
brew install dart-beta
dart --version
- name: Testing
script: |
dart test
- name: Static analysis
script: |
dart analyze
- name: Check for publishing
script: |
pub publish --dry-run
- name: Publish to pub.dev
script: |
echo $CREDENTIALS | base64 --decode > "$FLUTTER_ROOT/.pub-cache/credentials.json"
flutter pub publish --dry-run
flutter pub publish -f
您需要手动上传一次软件包到
pub.dev。这将在 pub cache 目录下创建credentials.json文件(MacOS 和 Linux 上为~/.pub-cache/credentials.json,Windows 上为%APPDATA%/Pub/Cache\credentials.json)。加密Codemagic的文件,并更新
CREDENTIALS环境变量的值。
-
将YAML文件放在项目的根目录下,并将其推送到你的版本库。
-
点击 "开始新的构建",选择你的分支和工作流,并将其推送到你的项目库中。
- 选择你的分支和工作流,然后点击开始新的构建。
这将在Codemagic上开始一个新的构建。
已完成建设
版本解算
现在我们已经看到了空安全迁移过程和使用Codemagic的自动发布,对于包作者来说,了解版本求解对于最终用户来说是非常重要的。
我们将以characters包为例,从最终用户的角度来学习理解。
我没有使用我们用来学习空安全迁移过程的包,因为它没有发布到
pub.dev,使用GitHub repo版本的包也不能正确地让你感受到版本求解。
稳定频道上的Dart
首先,我们来看看在Dart的稳定频道上,版本求解是如何正常工作的。
目前,一个Demo Dart应用的pubspec.yaml文件是这样的。
name: version_demo
description: A sample command-line application.
environment:
sdk: '>=2.8.1 <3.0.0'
dependencies:
characters: ^1.0.0
dev_dependencies:
pedantic: ^1.9.0
test: ^1.14.4
这里,我刚刚导入了characters包的最新stable版本。
版本号前的小括号(^)有助于使最新的版本与当前的版本(即有非中断性修改的版本)兼容。^1.0.0相当于>=1.0.0 <2.0.0。
但如果包还没有达到主要版本(1.0.0),比如包的版本是0.6.1,这里使用逗号(^0.6.1)就相当于>=0.6.1 <0.7.0。
在我们的例子中,将版本指定为characters: ^0.3.0 (相当于>=0.3.0 <0.4.0)将解析为0.3.1。这是因为如果你在 pub.dev 上检查characters的版本,你会看到这个。
提示:在运行 pub get 后,你可以通过 pubspec.lock 来检查正在使用的软件包的确切版本。
# pubspec.lock
characters:
dependency: "direct main"
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.1"
现在,你甚至可以通过使用any来跳过指定某个包的任何版本。
dependencies:
characters: any
如果你在这之后运行pub upgrade,它将检索到最新的稳定版本的软件包。
# pubspec.lock
characters:
dependency: "direct main"
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
所以,作为一个包的作者,你应该遵循上面讨论的包的版本。
Dart在测试版频道
在写这篇文章的时候,Dart的null safety是测试版(所以你不能在稳定频道中使用任何null safe的包)。要在你的应用中使用具有空安全的包,你首先要更新SDK版本。
environment:
sdk: ">=2.12.0-133.2.beta <3.0.0"
现在,你可以使用满足SDK约束的空安全版本的包。
dependencies:
characters: ^1.1.0-nullsafety.5
在这里,类似的版本语法也可以使用,但使用逗号将检索包的最新空安全版本--例如,定义^1.1.0-nullsafety.4将解析为1.1.0-nullsafety.5(最新版本)。
但如果你使用any作为软件包的版本,那么它将解析为最新的稳定版本(而不是null-safe版本)。
dependencies:
characters: any
# pubspec.lock
characters:
dependency: "direct main"
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
上面讨论的所有概念(关于Dart应用)也适用于Flutter应用。
请记住。对于包的作者来说,即使你已经将你的包迁移到了null安全版本,你仍然可以在发布null安全版本的同时保持一个稳定的版本。
结束语
您现在已经准备好将自己的Flutter/Dart包迁移到null安全,并将其发布到pub.dev。希望这篇文章能帮助你深入了解迁移过程和版本解决如何为终端用户工作。
参考文献
Souvik Biswas是一个充满激情的移动应用开发者(Android和Flutter)。在他的职业生涯中,他曾开发过许多移动应用,他喜欢在Github上进行开源贡献。他目前正在印度信息技术学院Kalyani攻读计算机科学与工程专业的技术学士学位。他还在 "Medium-Flutter社区 "上撰写Flutter文章。
通过www.DeepL.com/Translator(免费版)翻译