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
更多
- 关于
.let
关键字的讨论 https://github.com/dart-lang/language/issues/2703 - 空安全模式 https://github.com/dart-lang/language/blob/main/accepted/3.0/patterns/feature-specification.md
示例代码
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
更多关于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 Group、Stack 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"
}