[译][官方文档] Flutter/Dart 状态管理库 Riverpod (九)- 概要 - WebSocket 和同步执行

原文链接:Websockets and synchronous execution | Riverpod

pub:riverpod | Dart Package (flutter-io.cn)

译时版本: 2.4.9


之前翻译过 Riverpod 的官方文档,现在随着版本更新,官方文档又多了很多新内容,所以再补充翻译一下。

之前翻译过的内容,现在官方文档有中文了。
Flutter状态管理库Riverpod官方文档翻译汇总 - 掘金 (juejin.cn)


WebSocket 和同步执行

迄今为止,只说明了如何创建 Future 。

这是有意为之的,因为 Future 是 Riverpod 应用应当如何构建的核心。 不过,必要时,Riverpod 也支持其它格式。

特别是,除了 Future ,provider 还可自由用于:

  • 同步式返回对象,比如创建 "Repository" 。
  • 返回 Stream (流),比如监听 websocket 。

返回 Future 和返回 Stream 或对象总体上非常相似。 该篇可认为是用于这些场景的细微差别的说明和各种提示。

同步式返回对象

要同步式创建对象,要确保 provider 没有返回 Future :

dart 复制代码
@riverpod
int synchronousExample(SynchronousExampleRef ref) {
  return 0;
}

当 provider 同步式创建对象时,这会影响对象的消费方式。 特别是同步值不会封装在 "AsyncValue" 里面。

dart 复制代码
Consumer(
  builder: (context, ref, child) {
    // 该值不会封装在 "AsyncValue" 里面。
    int value = ref.watch(synchronousExampleProvider);

    return Text('$value');
  },
);

该差别的结果就是如果 provider 抛出了错误,尝试读取值会再次抛出错误。 作为替换方案,使用 ref.listen 时,"onError" 回调会被调用。

可监听对象的考量

可监听对象,如 ChangeNotifier 或 StateNotifier 是不支持的。

如果,为了兼容性的原因,需要和该类对象进行交互,一个变通方案是将其通知机制移植到 Riverpod 。

csharp 复制代码
/// provider 创建了 ValueNotifier ,并且在值改变时更新它的 listener (监听器)。
@riverpod
ValueNotifier<int> myListenable(MyListenableRef ref) {
  final notifier = ValueNotifier(0);

  // provider 清理后对 notifier 进行清理。
  ref.onDispose(notifier.dispose);

  // ValueNotifier 更新时通知 provider 的 listener (监听器)。
  notifier.addListener(ref.notifyListeners);

  return notifier;
}

信息

万一需要多次该逻辑,那值得注意一下将逻辑共有! "ref" 对象是被设计成可组合的。这样将清理/监听逻辑放到 provider 之外:

csharp 复制代码
extension on Ref {
  // 可以移除 Ref 扩展前面的逻辑。
  // 这样可以在 provider 之间重用逻辑
  T disposeAndListenChangeNotifier<T extends ChangeNotifier>(T notifier) {
    onDispose(notifier.dispose);
    notifier.addListener(notifyListeners);
    // 返回 notifier 便于使用
    return notifier;
  }
}

@riverpod
ValueNotifier<int> myListenable(MyListenableRef ref) {
  return ref.disposeAndListenChangeNotifier(ValueNotifier(0));
}

@riverpod
ValueNotifier<int> anotherListenable(AnotherListenableRef ref) {
  return ref.disposeAndListenChangeNotifier(ValueNotifier(42));
}

监听 Stream (流)

现代应用的一个常见使用场景是和 websocket 交互,比如和 Firebase 交互或订阅 GraphQL 。

和这些 API 交互通常是通过监听 Stream (流)来完成。

为了助力此类需求,Rvierpod 天然支持 Stream (流)对象。如使用 Future ,对象会被转换成 AsyncValue :

dart 复制代码
@riverpod
Stream<int> streamExample(StreamExampleRef ref) async* {
  // 每 1 秒钟生成 0 到 41 之间的一个数字。
  // 这可替换成源于 Firestore 或 GraphQL 的 Stream (流)或其它任何处理。
  for (var i = 0; i < 42; i++) {
    yield i;
    await Future<void>.delayed(const Duration(seconds: 1));
  }
}

class Consumer extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Stream 流在这里被监听,并转换成了 AsyncValue 。
    AsyncValue<int> value = ref.watch(streamExampleProvider);

    // 可用 AsyncValue 处理加载中/错误状态和表示数据。
    return switch (value) {
      AsyncValue(:final error?) => Text('Error: $error'),
      AsyncValue(:final valueOrNull?) => Text('$valueOrNull'),
      _ => const CircularProgressIndicator(),
    };
  }
}

信息

Riverpod 没有考虑自定义 Stream (流)的实现,如 RX 的 BehaviorSubject 。因此,返回 BehaviorSubject 不会同步向组件暴露 value (值),即使在创建时已经可用。

禁用 Stream/Future 向 AsyncValue 的转换

Riverpod 默认会把 Stream 和 Future 转换为 AsyncValue 。 尽管不常用,但也可以禁用该行为,将返回类型封装到 Raw 的类型定义中即可禁用。

警告

通常不建议禁用 AsyncValue 的转换。只可在完全了解行为目的时这样做。

scala 复制代码
@riverpod
Raw<Stream<int>> rawStream(RawStreamRef ref) {
  // "Raw" 是一个类型定义。不需要将返回值封装在 "Raw" 构造函数中。
  return const Stream<int>.empty();
}

class Consumer extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 值不再会转换成 AsyncValue ,创建的 Stream (流)会原样返回。
    Stream<int> stream = ref.watch(rawStreamProvider);
    return StreamBuilder<int>(
      stream: stream,
      builder: (context, snapshot) {
        return Text('${snapshot.data}');
      },
    );
  }
}

相关推荐
Geek_Vison5 小时前
保险APP已经用了Flutter,还能接入小程序吗?
flutter·小程序·uni-app·mpaas·小程序容器
FungLeo5 小时前
成为全栈·Flutter App 篇·go_router 与四 Tab App Shell:保留导航状态、深链和登录回跳
flutter·移动开发·成为全栈·go_router·路由设计·深链接
m0_738185826 小时前
Flutter 鸿蒙化实战:screen_protector 适配 OpenHarmony,防截屏/防泄露
flutter·华为·harmonyos·鸿蒙
梦想的颜色11 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
yuanlaile1 天前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭2 天前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白2 天前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫2 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘2 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185823 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙