Dart 从另一个流监听器中产生流事件

nil*_*arp 3 stream dart flutter

我有一个生成stream特定事件的函数。现在我有一个来自存储服务的流,它有自己的事件。寻找一种在storage stream.

此代码片段不起作用。

Stream<BlocState> mapEventToState(
    BlocEvent event,
  ) async* {
  if (event is UploadData) {
    yield UploadDataProgress(progress: 0.0);
    final Storage storage = Storage();
    final Stream<StorageEvent> upload = storage.upload(event.data);

    upload.listen((StorageEvent storageEvent) async* {
      print('***** Listener: ${storageEvent.type} - ${storageEvent.progress}');

      if (storageEvent.type == StorageEventType.error) {
        yield UploadDataError(errorMessage: storageEvent.error);
      }

      if (storageEvent.type == StorageEventType.success) {
        yield UploadDataSuccess();
      }

      if (storageEvent.type == StorageEventType.progress) {
        yield UploadDataProgress(progress: storageEvent.progress);
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:调试打印有效,但事件未发送到侦听器。

***** Listener: StorageEventType.progress - 0.01924033836457124
***** Listener: StorageEventType.progress - 0.044581091468101464
***** Listener: StorageEventType.progress - 0.6986233206170177
***** Listener: StorageEventType.progress - 1.0
Run Code Online (Sandbox Code Playgroud)

Gaz*_*kus 16

您的yields 是从匿名函数中产生的,(StorageEvent storageEvent) async* {而不是从mapEventToState.

只需简单地更换listen()await for应该工作。

Stream<BlocState> mapEventToState(
    BlocEvent event,
  ) async* {
  if (event is UploadData) {
    yield UploadDataProgress(progress: 0.0);
    final Storage storage = Storage();
    final Stream<StorageEvent> upload = storage.upload(event.data);

    await for (StorageEvent storageEvent in upload) {
      print('***** Listener: ${storageEvent.type} - ${storageEvent.progress}');

      if (storageEvent.type == StorageEventType.error) {
        yield UploadDataError(errorMessage: storageEvent.error);
      }

      if (storageEvent.type == StorageEventType.success) {
        yield UploadDataSuccess();
      }

      if (storageEvent.type == StorageEventType.progress) {
        yield UploadDataProgress(progress: storageEvent.progress);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

物有所值。我有一个类似的问题,我订阅了 Firebase 快照并尝试根据文档数据产生事件。

如果我使用 await-for 范式,我将无法获得订阅句柄。结果,当我想关闭 BLoC 时,停止读取流变得很痛苦。

我找到了一个全面的解决方案。

Stream<BlocState> mapEventToState(BlocEvent event) async* {
  if (event is FetchEvent) {
    yield LoadingState();
    _subscription = SomeStream(event.someKey).listen((snapshot) {
      add(OnSnapshotEvent(snapshot));
    });
  }

  if (event is OnSnapshotEvent) {
    if (SomeCondition(event.snapshot)) {
      yield SomeResultState();
    } else {
      yield SomeOtherState();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,我就有了订阅的句柄,所以我总是可以很好地清理。