Flutter类型化结果处理插件typed_result的使用
Flutter类型化结果处理插件typed_result的使用
typed_result
插件提供了一个方便的 Result
单子(monad),用于表示成功和错误。Result<T, E>
类可以是成功 (Ok<T>
) 或者错误 (Err<E>
)。
特性
typed_result
插件提供了以下便利方法:
- 获取值:
get
、getOr
、getOrThrow
、getError
、getErrorOr
和getErrorOrThrow
- 映射
Result
值:map
、mapError
和mapBoth
- 基于结果执行代码块:
onSuccess
、onFailure
和when
- 捕获异常并转换为错误:
runCatching
- 根据空值将任何对象包装为
Result
:toResultOr
- 测试
Result
的自定义匹配器
使用方法
Result<T, E>
不能直接实例化。要创建一个 Result
,只需创建 Ok<T>
或 Err<E>
的实例。
var result = Ok(1); // 作为 Ok<int>
var result = Err(""); // 作为 Err<String>
Result<int, String> result = Ok(1); // 作为 Result<int, *>, 其中 * 可以是任何类型
Result<int, String> result = Err(""); // 作为 Result<*, String>, 其中 * 可以是任何类型
// 作为函数的返回值
Result<int, String> getData() {
if (condition) {
return Ok(1);
} else {
return Err("");
}
}
完整示例Demo
以下是一个完整的示例,展示了如何使用 typed_result
插件的各种功能:
// ignore_for_file: avoid_print
import 'package:typed_result/typed_result.dart';
class DateException implements Exception {}
class ChildDateException implements DateException {}
/// 模拟一个真实的仓库调用,通常会有一个自定义类来表示预期的失败。
/// 如果 [forceFailure] 为 false,则正常返回当前日期的 `Ok`。
/// 如果 [forceFailure] 为 true,则返回自定义异常类的 `Err`。
Result<DateTime, DateException> getDate(bool forceFailure) {
var now = DateTime.now();
if (!forceFailure) {
return Ok(now);
} else {
return Err(DateException());
}
}
void main() async {
var ok = getDate(false);
var err = getDate(true);
/// 展示 `Result` 实例的属性
void instances() {
print("\nInspecting instances of Result");
print(ok);
print("ok.isSuccess: ${ok.isSuccess}");
print("ok.isFailure: ${ok.isFailure}");
print(err);
print("err.isSuccess: ${err.isSuccess}");
print("err.isFailure: ${err.isFailure}");
}
/// 展示如何从 `Result` 中获取值
void getters() {
print("\n`get`");
print(ok.get()); // 获取成功值
try {
print(err.get()); // 尝试获取失败值,会抛出异常
} catch (e) {
print("Exception was thrown because it was a failure result");
}
print("\n`getOr`");
print(ok.getOr(() => DateTime(2000))); // 获取成功值或默认值
print(err.getOr(() => DateTime(2000))); // 获取失败值或默认值
print("\n`getOrThrow`");
print(ok.getOrThrow()); // 获取成功值或抛出异常
try {
err.getOrThrow(); // 尝试获取失败值,会抛出异常
} catch (e) {
print("Exception was thrown because it was a failure result");
}
print("\n`getError`");
print(ok.getError()); // 获取成功结果的错误值,返回 null
print(err.getError()); // 获取失败结果的错误值
print("\n`getErrorOr`");
print(ok.getErrorOr(() => ChildDateException())); // 获取成功结果的错误值或默认值
print(err.getErrorOr(() => ChildDateException())); // 获取失败结果的错误值或默认值
print("\n`getErrorOrThrow`");
try {
ok.getErrorOrThrow(); // 获取成功结果的错误值或抛出异常
} catch (e) {
print("Exception was thrown because it was a success result");
}
print(err.getErrorOrThrow()); // 获取失败结果的错误值
}
/// 展示如何将当前 `Result` 值映射为新的 `Result`
void map() {
print("\n`map`");
print(ok.map((value) => "Mapping success at $value")); // 映射成功值
print(err.map(noop)); // 映射失败值,不会执行
print("\n`mapError`");
print(ok.mapError(noop)); // 映射成功值的错误,不会执行
print(err.mapError((_) => "Mapping error")); // 映射失败值的错误
print("\n`mapBoth`");
print(ok.mapBoth(
success: (_) => "Mapping a success value", // 映射成功值
failure: noop, // 映射失败值,不会执行
));
print(err.mapBoth(
success: noop, // 映射成功值,不会执行
failure: (_) => "Mapping a failure value", // 映射失败值
));
}
/// 展示如何基于 `Result` 的结果执行代码块
void on() {
print("\n`on`");
ok.onSuccess((_) => print("onSuccess")).onFailure(noop); // 成功时执行
err.onSuccess(noop).onFailure((_) => print("onFailure")); // 失败时执行
}
/// 展示另一种基于 `Result` 的结果执行代码块的方式
void when() {
print("\n`when`");
ok.when(
success: (_) => print("When [success]"), // 成功时执行
failure: noop, // 失败时不会执行
);
err.when(
success: noop, // 成功时不会执行
failure: (_) => print("When [failure]"), // 失败时执行
);
}
/// 展示如何安全地调用方法,并将任何异常转换为 `Result` 错误
void catching() {
print("\n`runCatching`");
print(runCatching(() => DateTime.now())); // 正常执行
print(runCatching(() => throw DateException())); // 捕获异常并转换为 `Result` 错误
}
/// 展示如何根据空值将任何对象转换为 `Result`
void toResult() {
print("\n`toResult`");
print(DateTime.now().toResultOr(() => DateException())); // 非空值转换为 `Ok`
print(null.toResultOr(() => DateException())); // 空值转换为 `Err`
}
/// 展示如何处理 `Future` 类型的 `Result`
Future<void> future() async {
print("\n`Futures`");
final futureOk = Future.value(ok); // Future<Result<DateTime, DateException>>
final futureErr = Future.value(err); // Future<Result<DateTime, DateException>>
await futureOk.when(success: (value) => print("Future(ok).when(success): $value"), failure: noop);
await futureErr.when(success: noop, failure: (error) => print("Future(err).when(failure): $error"));
await futureOk.onSuccess((value) => print("Future(ok).onSuccess: $value"));
await futureErr.onSuccess(noop);
await futureOk.onFailure(print);
await futureErr.onFailure((error) => print("Future(err).onFailure: $error"));
}
// 调用所有示例方法
instances();
getters();
map();
on();
when();
catching();
toResult();
await future();
}
// 一个永远不会被调用的占位方法,用于演示目的
void noop(dynamic param) => print("A stub method that is never called; Used for demonstration purposes");
更多关于Flutter类型化结果处理插件typed_result的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter类型化结果处理插件typed_result的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用typed_result
插件来进行类型化结果处理的示例代码。typed_result
插件可以帮助你更好地管理异步操作的结果,特别是当你希望结果具有明确的类型时。
首先,确保你已经在pubspec.yaml
文件中添加了typed_result
依赖:
dependencies:
flutter:
sdk: flutter
typed_result: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来,让我们编写一些代码来演示如何使用typed_result
。
示例代码
- 创建一个异步函数,模拟一个网络请求或耗时操作
import 'dart:async';
Future<TypedResult<String, String>> fetchData() async {
// 模拟网络请求或耗时操作
await Future.delayed(Duration(seconds: 2));
// 假设这里可能成功返回一个字符串,或者失败返回一个错误信息
bool success = true; // 你可以根据实际情况改变这个值来模拟成功或失败
if (success) {
return TypedResult.success("这是从服务器获取的数据");
} else {
return TypedResult.failure("请求失败,请稍后重试");
}
}
- 在UI中处理这个结果
import 'package:flutter/material.dart';
import 'package:typed_result/typed_result.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Typed Result Demo'),
),
body: Center(
child: FutureBuilder<TypedResult<String, String>>(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
final result = snapshot.data;
if (result?.isSuccess ?? false) {
return Text('Success: ${result.data}');
} else {
return Text('Failure: ${result?.error ?? 'Unknown error'}');
}
}
},
),
),
),
);
}
}
解释
-
fetchData函数:
- 使用
Future.delayed
模拟网络请求或耗时操作。 - 根据模拟的成功或失败条件,返回
TypedResult.success
或TypedResult.failure
。
- 使用
-
UI部分:
- 使用
FutureBuilder
来异步获取fetchData
的结果。 - 根据
snapshot.connectionState
判断当前状态(等待、完成、错误)。 - 如果结果是成功的,显示成功数据;如果结果是失败的,显示错误信息。
- 使用
通过这种方式,你可以使用typed_result
插件来更清晰地处理异步操作的结果,使得代码更具可读性和可维护性。