[译][官方文档] 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" 回调会被调用。

可监听对象的考量

可监听对象,如 ChangeNotifierStateNotifier 是不支持的。

如果,为了兼容性的原因,需要和该类对象进行交互,一个变通方案是将其通知机制移植到 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/FutureAsyncValue 的转换

Riverpod 默认会把 StreamFuture 转换为 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}');
      },
    );
  }
}

相关推荐
helloxmg3 小时前
鸿蒙harmonyos next flutter通信之MethodChannel获取设备信息
flutter
helloxmg3 小时前
鸿蒙harmonyos next flutter混合开发之开发package
flutter·华为·harmonyos
lqj_本人1 天前
flutter_鸿蒙next_Dart基础②List
flutter
lqj_本人1 天前
flutter_鸿蒙next_Dart基础①字符串
flutter
The_tuber_sadness1 天前
【Flutter】- 基础语法
flutter
helloxmg1 天前
鸿蒙harmonyos next flutter通信之BasicMessageChannel获取app版本号
flutter
linpengteng2 天前
使用 Flutter 开发数字钱包应用(Dompet App)
前端·flutter·firebase
云兮Coder2 天前
鸿蒙 HarmonyNext 与 Flutter 的异同之处
flutter·华为·harmonyos