Flutter插件castor的使用方法详解

Flutter插件castor的使用方法详解

CastOr 🦫

CastOr 提供了 .castOr<T>(()), .castOrNull<T>() 辅助函数和扩展,用于在处理非类型化数据时安全地转换/强制类型,并提供默认值。该包还提供了 .let<T>() 实现(类似于 Kotlin 的实现)。

此包旨在解决在 Dart 项目中处理空安全时的两个典型问题:

  • 使用 as 强制类型转换可能会失败,如果未确保类型前。
  • 使用 ! 后缀的空值提升运算符也应避免使用。

考虑以下代码:

void main() {
  dynamic a = 3;
  final String? s;
  try {
    s = a as String;
  } catch (e) {
    s = null;
  }
}

这可以被解决:

import 'package:castor/castor.dart';

void main() {
  dynamic dyn = null;
  final obj = (dyn as Object?);
  // 基本的 [castOr] 总是期望获取输入类型的解包值
  int b = obj.castOr<String>('alternative string').length;
  int c = castOr<int>('alternative string').length;

  // 等效的 [castOrNull] 只接受一个可空值,当强制类型转换错误时
  bool? asHelper = castOrNull<bool>('alternative string').length;
  bool? asExt = obj?.castOrNull();

  int? s = castOrNull<String>('alternative string')?.length;
  /// 和 [a] 一个 Object?
  int s2 = a?.castOr<String>((val) => 'alternative string').length;
  int? s = a?.castOrNull<String>()?.length;
}

目前这样是没问题的,但如果有人删除了 if 子句,这将最终导致崩溃,因为静态分析不会检查这些代码。

Flutter插件castor使用

.castOr 强制类型或提供默认值

你希望确保给定值是正确的类型,而不需要混合使用易出错的 as 关键字。考虑以下代码:

void main() {
  dynamic a = 3;
  final String? s;
  try {
    s = a as String;
  } catch (e) {
    s = null;
  }
}
import 'package:castor/castor.dart';

void main() {
  /// 考虑 [a] 是动态的
  int s2 = castOr<String>('alternative string').length;
  int? s = castOrNull<String>('alternative string')?.length;
  /// 和 [a] 是 Object?
  int s2 = a?.castOr<String>((val) => 'alternative string').length;
  int? s = a?.castOrNull<String>()?.length;
}

推升

使用 ! 进行推升应该避免使用。考虑以下代码:

if (this.a != null) this.a!.length;

目前这样是没问题的,但如果有人删除了 if 子句,这将最终导致崩溃,因为静态分析不会检查这些代码。

其他信息

在编写此包之前,我发现了很多其他替代解决方案,大多数都试图模仿 Kotlin 的 .let 行为和其他用于确保代码中每个地方的空安全的 guard 关键字。

我选择发布这个小工具是因为它的名字很可爱,但更重要的是它对你的代码库影响很小。

关于 Dart 和空安全,当你开始相信 Dart 的空安全时,有三个常见的陷阱:

  • 首先是 dynamic 关键字和 ! 后缀的空值提升运算符。两者都应该避免使用,你应更倾向于使用 Object?,虽然不完全等价,但可以简单切换。
  • 其次,你应该检查 as 关键字,没有将其封装到 try/catch 块中或用 if (a is b) 控制块前缀。
  • 最后,有很多会抛出的方法,你无法通过静态方法避免它们,除非使用像 DCM 这样的工具。

科普

“Castor” 在法语中是 “海狸” 的意思。这就是为什么你会在某些地方找到海狸符号 🦫。

             ██  ██████████████▓▓██  ████
           ██▒▒██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██▒▒▒▒██
           ██▒▒██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██▒▒▒▒██
             ██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██
           ██▒▒▒▒▒▒██▒▒▒▒██▒▒▒▒▒▒▒▒▒▒▒▒▓▓
         ██▒▒▒▒▒▒▒▒██▒▒▒▒██▒▒▒▒▒▒▒▒▒▒▒▒██
       ██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██
     ██▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██
     ██▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒██  ░░
     ██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒██
     ██▒▒▒▒██▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒▒▒██
     ██▒▒▒▒▓▓██████████████████▓▓▒▒▒▒▒▒▒▒▒▒▓▓▒▒██
     ▓▓▒▒▒▒▒▒▓▓██    ██    ██▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒██
     ██▒▒▒▒▒▒▒▒██    ██    ██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██
     ██▒▒▒▒▒▒▒▒██    ██    ██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒▒██
     ██▓▓▒▒▒▒▒▒▒▒██████████▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒▒██
       ██▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓██░░██▒▒▒▒▒▒▒▒▒▒▓▓▒▒██
         ████▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓██░░▒▒▒▒██▒▒▒▒▒▒▒▒▒▒▓▓▒▒██
             ████▓▓▒▒▓▓██████▓▓██░░▒▒██████▒▒▒▒▒▒▒▒▒▒▒▒▒▒██    ████████
                 ██▓▓██▒▒▒▒▓▓██░░▒▒██▓▓▒▒▒▒██▒▒▒▒██▒▒▓▓▒▒██  ██▒▒▒▒▒▒▒▒██
                 ██▒▒▒▒▒▒▓▓██░░▒▒▒▒▒▒██▓▓▒▒▒▒▒▒▓▓██▒▒▒▒▓▓▒▒██▒▒▓▓▓▓▒▒▓▓▒▒██
                 ██▓▓▓▓▓▓██░░▒▒▒▒▒▒██▓▓██▓▓▓▓▓▓██▓▓▒▒▒▒▒▒▒▒██▓▓▒▒▓▓▓▓▓▓▓▓██
                 ██████████▒▒▒▒▒▒██▓▓▓▓▓▓██████▓▓▒▒▒▒▓▓▒▒▒▒██▓▓▓▓▓▓▓▓▒▒▓▓██
                 ██▓▓██░░░░██▒▒▒▒██▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒██▓▓▓▓▓▓▓▓▓▓▓▓██
                 ██▓▓▓▓██░░░░████▒▒██▒▒▒▒▓▓▒▒▒▒▒▒▓▓▒▒▒▒▒▒▒▒██▓▓▒▒▓▓▓▓▓▓████
                   ██▓▓▓▓████▓▓▓▓██▒▒██▒▒▒▒▓▓▒▒▒▒▒▒▒▒▒▒▒▒██▓▓▓▓▓▓▓▓████
                   ██▓▓▓▓▓▓▓▓▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓██▓▓▓▓▒▒████
                 ██████▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓██████████████████
               ██░░░░░░██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██░░░░░░░░░░░░████████
             ██▒▒██▒▒▒▒▒▒██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▒▒▒▒▒▒██▒▒██▒▒▒▒██
             ██▓▓██████████████▓▓████████████████████████████▓▓
 credits : https://textart.sh/topic/beaver

更多

示例代码

import 'package:castor/castor.dart';

dynamic fetchDynamicValue([dynamic input]) {
  return input;
}

class Url {
  Url._();
  static Url? tryParse(String url) {
    return url.isEmpty ? null : Url._();
  }
}

void main() {
  final myValue = fetchDynamicValue() as Object?;

  /// 你得到一个意外的值,并且你想确保类型正确
  /// 或提供另一个值。
  myValue?.castOrNull<int>()?.isOdd;

  /// 你也可以通过提供一个替代值来映射它
  /// 或提供另一个值。
  myValue?.castOrNull<int>((it) => 32)?.isOdd;
  final int myNum = (null as Object?).castOr((it) => 32);

  /// 或者即使解包并在任何情况下提供一个默认值,
  /// 这个方法重复了优雅的 `??` 操作符,如果你计划
  /// 链接调用,这是一个有用的助手。
  (null as Object?).castOr<int>((it) => 32).isOdd;
  final int myNumBis = (null as Object?).castOr((it) => 32);

  /// 当输入值是一个动态值时,你不应该尝试使用 `castOr`
  /// 作为扩展,因为它将会
  final dynamic myDynamicRef = fetchDynamicValue();
  castOr<int>(myDynamicRef, (it) => 32).isOdd;
  castOrNull<int>(myDynamicRef)?.isOdd;

  /// 你也可以将样本值转换为另一种类型。
  /// 这在链式方法调用时非常有用。
  (myValue)
      // 将这个值映射为一个 int 的集合
      ?.castOr<Set<int>>((it) => {it is int ? it : 43})
      // 并将其取回为一个 int
      .castOr<int>((it) => it?.toList().elementAtOrNull(0) ?? 34)
      // 你可以在这里提供几乎任何转换
      .isFinite;

  /// 你也可以将值转换为另一种类型
  final result = 42.castOr<Set<int>>((i) => {i ?? 45});

  /// 经典情况是你必须处理可空值和可空参数,考虑以下示例...
  /// ```dart
  ///   Uri? valueTransformer(String? url) {
  ///     final thisUri = url;
  ///     if (thisUri == null) return null;
  ///     return Uri.tryParse(thisUrl);
  ///   }
  /// ```
  final String? urlString = '...';
  final url1 = urlString?.let<Url>(Url.tryParse);
  final Url? url2 = urlString?.let(Url.tryParse); // 注意推断
}

更多关于Flutter插件castor的使用方法详解的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件castor的使用方法详解的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


castor 是一个在 Flutter 社区中比较小众且文档较少的插件,因此它的具体功能和用法可能不为大多数开发者所熟知。由于你提到的“未知功能”,我们可以尝试从以下几个方面来推测和理解 castor 插件可能的用途和用法:

1. 查阅源代码

如果插件的文档缺失或不够详细,最好的办法是直接查看插件的源代码。你可以在 pub.dev 上找到 castor 插件的页面,并访问其 GitHub 仓库或下载源代码进行分析。

  • pubspec.yaml 中添加依赖:
    dependencies:
      castor: ^版本号
    
  • 运行 flutter pub get 下载依赖。
  • 在项目目录下找到 .pub-cache 文件夹,查看插件的源代码。

2. 查看示例代码

如果插件提供了示例代码(通常在 example/ 目录下),可以通过运行示例代码来理解插件的功能。示例代码通常会展示插件的主要功能和用法。

3. 尝试基本用法

如果插件没有详细的文档,可以尝试通过导入插件并使用其提供的类和函数来探索其功能。例如:

import 'package:castor/castor.dart';

void main() {
  // 尝试初始化插件或使用其提供的功能
  var castor = Castor();
  castor.someFunction(); // 假设插件提供了某个函数
}

4. 查看插件的 README.md 文件

通常情况下,插件会在 README.md 文件中提供基本的介绍和用法说明。即使插件的功能未定义,README.md 文件中可能也会包含一些有用的信息。

5. 社区和论坛

你可以在 Flutter 社区(如 Flutter Dev Google GroupStack Overflow 等)中提问,看看是否有其他开发者使用过 castor 插件并分享了他们的经验。

6. 联系插件作者

如果你仍然无法确定插件的功能,可以考虑联系插件的作者或维护者。通常在插件的 pubspec.yaml 或 GitHub 仓库中可以找到作者的联系信息。

7. 推测功能

如果上述方法都无法确定插件的功能,你可以尝试根据插件的名称和类名来推测其功能。例如,castor 可能与“转换”、“投射”或“广播”有关,具体功能可能与数据类型转换、流处理或网络通信相关。

示例代码(假设 castor 用于数据转换):

import 'package:castor/castor.dart';

void main() {
  var castor = Castor();
  
  // 假设 castor 可以将字符串转换为整型
  int number = castor.toInt("123");
  print(number); // 输出 123
  
  // 假设 castor 可以将整型转换为字符串
  String str = castor.toString(456);
  print(str); // 输出 "456"
}
回到顶部