记录一个Flutter空安全升级问题

最近碰到一个奇怪的问题

先来看个现象

工程结构

.
├── README.md
├── android
├── build
├── ios
├── lib
├── pubspec.lock
├── pubspec.yaml
├── subpackage
├── test
└── webview_demo.iml

子工程空安全检测正确✅

jiodg45@jiodg45s-MacBook-Pro subpackage % dart pub outdated --mode=null-safetyShowing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
[✓] indicates versions opting in to null safety.

主工程检测却发现子工程出现空安全问题❌

jiodg45@jiodg45s-MacBook-Pro webview_demo % dart pub outdated --mode=null-safety
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:
subpackage    ✗0.0.1 (path)  ✗0.0.1 (path)  ✗0.0.1 (path)  ✗0.0.1 (path)

十分诡异,于是开启了--verbose查看详细日志,空安全检测具体命令dart pub outdated --mode=null-safety --verbose

可以看到空安全检测主要是对每个库的sdk版本与2.12.0进行比较

  1. 获取依赖,包含git/path/pub三个级别的依赖
  2. 其中工程外的pub依赖关系保存在/Users/jiodg45/.pub-cache/hosted/pub.dartlang.org/.cache/cupertino_icons-versions.json.,对应路径为$HOME/$PUB_CACHE/hosted/HOST_PUB_URL/.cache/{package_name}-versions, 此部分是从pub库上获取,通过json中的environment获取到sdk版本,用于后续比较
  3. 工程内的依赖关系保存在pubspec.lock文件中,gitpath相关的一级依赖也会被添加到此仓库中,以来类型为dependency: transitive
  4. 这样仓库的所有的依赖关系可以从三个文件一次进行查找, pubspec.yaml->pubspec.lock->`` H O M E / HOME/ HOME/PUB_CACHE/hosted/HOST_PUB_URL/.cache/{package_name}-versions

对应的代码可以在pub库的outdated.dart中查看,省略后的关键代码如下,主要逻辑集中在supportsNullSafety,逐一查找package的dart sdkVersion,然后与2.12.0比较

https://github.com/dart-lang/pub/blob/master/lib/src/command/outdated.dart
-> OutdatedCommand

 @override
  Future<List<List<_MarkedVersionDetails>>> markVersionDetails(
      List<_PackageDetails> packages) async {
    final nullSafetyMap =
        await log.spinner('Computing null safety support', () async {
      /// Find all unique ids.
      ...
      return Map.fromEntries(
        await Future.wait(
          ids.map(
            (id) async => MapEntry(
                id,
                (await id.source.bind(cache).describe(id))
                    .languageVersion
                    .supportsNullSafety), 
    ...

所以当子工程的pubspec.yamlsdkVersion指定的最低版本低于2.12.0时会报空安全检测异常. 因此在升级时一定要修改sdk的最低约束,防止误检.

environment:
  sdk: ">=2.12.0 <3.0.0"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 2.0 之后,Dart 默认启用了安全Null Safety),因此在使用二维码扫描插件时需要使用安全的 API。 对于 `qr_code_scanner` 插件,可以使用 `qr_code_scanner_nullsafety` 包,其使用方式与原始插件基本相同,只是 API 有所改变。以下是一个简单的示例: 1. 添加 `qr_code_scanner_nullsafety` 插件到 `pubspec.yaml` 文件中: ``` dependencies: qr_code_scanner_nullsafety: ^0.5.2 ``` 2. 导入 `qr_code_scanner_nullsafety` 包: ``` import 'package:qr_code_scanner_nullsafety/qr_code_scanner_nullsafety.dart'; ``` 3. 创建一个 `QRViewController` 和一个 `QRView`: ``` QRViewController? controller; final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); @override Widget build(BuildContext context) { return QRView( key: qrKey, onQRViewCreated: _onQRViewCreated, ); } void _onQRViewCreated(QRViewController newController) { controller = newController; controller!.scannedDataStream.listen((scanData) { // 处理扫描到的二维码 }); } ``` 注意,`QRViewController` 类型需要加上问号 `?`,表示这个对象可能为。在 `_onQRViewCreated()` 方法中,也需要对 `controller` 进行非判断,确保它不为。 对于 `barcode_scan` 插件,可以使用 `barcode_scan_null_safety` 包,使用方式与原始插件类似。以下是一个简单的示例: 1. 添加 `barcode_scan_null_safety` 插件到 `pubspec.yaml` 文件中: ``` dependencies: barcode_scan_null_safety: ^2.0.1 ``` 2. 导入 `barcode_scan_null_safety` 包: ``` import 'package:barcode_scan_null_safety/barcode_scan_null_safety.dart'; ``` 3. 调用 `scan()` 方法并处理返回的数据: ``` Future<void> scan() async { String barcode = await BarcodeScanner.scan(); // 处理扫描到的二维码 } ``` 对于 `barcode_scan_null_safety`,`scan()` 方法返回的类型为非的 `Future<String>`,不需要进行值检查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值