【问题标题】:Combine multiple BehaviorSubject streams into one?将多个 BehaviorSubject 流合并为一个?
【发布时间】:2023-03-18 05:27:01
【问题描述】:

我的目标是使用多个流,而不必嵌套 3 个以上的 StreamBuilder。

我已经在使用 rxdart,我研究了 mergewith,但我真的不明白使用它的正确语法?

我目前有一个名为 InfoBloc 的 Bloc 文件。这是InfoBloc里面的代码

  final _name = BehaviorSubject<String>();
  final _description = BehaviorSubject<String>();
  final _picture = BehaviorSubject<File>();

  Observable<String> get name => _name.stream.transform(_validateName);
  Observable<File> get picture => _picture.stream;
  Observable<String> get eventDescription =>
      _description.stream.transform(_validateMessage);

  final _validateMessage = StreamTransformer<String, String>.fromHandlers(
      handleData: (eventMessage, sink) {
    if (eventMessage.length > 0) {
      sink.add(eventMessage);
    } else {
      sink.addError(StringConstant.eventValidateMessage);
    }
  });

  var obs = Observable.merge([])
  final _validateName = StreamTransformer<String, String>.fromHandlers(
      handleData: (String name, sink) {
    if (RegExp(r'[!@#<>?":_`~;[\]\\|=+)(*&^%0-9-]').hasMatch(name)) {
      sink.addError(StringConstant.nameValidateMessage);
    } else {
      sink.add(name);
    }
  });

  void dispose() async {
    await _description.drain();
    _description.close();
    await _name.drain();
    _name.close();
    await _picture.drain();
    _picture.close();
  }

现在在小部件内部,我需要名称、图片和描述快照。所以我通常会这样做

 StreamBuilder(
   stream: _bloc.name,
   builder: (BuildContext context, AsyncSnapshot<String> snapshotName) {
     return StreamBuilder(
       stream: _bloc.eventDescription,
       builder: (BuildContext context, AsyncSnapshot<String> snapshotDescription) {
         return StreamBuilder(
           stream: _bloc.picture,
           builder: (BuildContext context, AsyncSnapshot<File> snapshotName) {

但是必须有更好的方法来做到这一点。

我的梦想是我可以在 InfoBloc 文件中创建可以组合所有这些流的东西,并且我只需使用一次 StreamBuilder 来流化组合的流。

【问题讨论】:

    标签: dart rxdart


    【解决方案1】:

    您可以检查Observable 类的combineLatest() 方法。它通过使用组合器函数将给定的 Streams 合并为一个 Observable 序列,这样生成的 Observable 不会发出,除非所有 Streams 都发出了至少一项。

    有很多combineLatest() 方法。但是由于您有 3 个 Streams,您可以使用 combineLatest3()

    例子-

    Observable.combineLatest3(
      new Observable.just("a"),
      new Observable.just("b"),
      new Observable.fromIterable(["c", "c"]),
      (a, b, c) => a + b + c)
    .listen(print); //prints "abc", "abc"
    

    您可以查看this 链接了解更多信息。

    更新 -

    您可以参考下面的示例在您的代码中使用该功能。

    Observable<String> get name => _name.stream.transform(_validateName);
    Observable<File> get picture => _picture.stream;
    Observable<String> get eventDescription => _description.stream.transform(_validateMessage);
    //Add this line to combine your Streams
    Observable<bool> readyToSubmit => Observable.combineLatest3(name, picture, eventdescription, (value1, value2, value3) => true);
    //We simply return true from the combiner function since we don't want to perform any operation on the Streams when combining.
    

    例如,我使用了bool 类型Observable。您可以将类型更改为您可以使用的Map&lt;String, dynamic&gt;' and add the Stream values into theMapif you want to access the data from all three streams. And in yourStreamBuilder`小部件-

    StreamBuilder(
       stream: _bloc.readyToSubmit,
       builder: //Your builder function here
    )
    

    希望这会有所帮助!

    【讨论】:

    • 如果只有较小的流子集发出项目会发生什么,例如只有 2 个流发出,而第 3 个流从不发出...那么组合流没有任何结果吗?
    • 是的,除非每个 Stream 至少发出一次,否则组合流不会发出结果。您可以参考此marble diagram 以获得更好的理解。如果您不确定任何一个 Streams 发射数据,那么您只需使用 combineLatest2() 组合两个并单独使用第三个。
    • 当您不确定流是否发出时,是否没有解决方案?你总是需要测试流吗?对不起初学者的问题,我是一个反应式编程菜鸟
    • 您可以使用startsWith() 方法来确保您的Observable 有一些初始数据,然后您可以使用comineLatest() 方法。更多关于此here.
    • 欣赏例子和cmets!我唯一的问题是我会把这个放在哪里?当你写 (a,b,c) => a + b + c 时,它怎么知道 a、b 和 c 是什么?我将如何使用它而不是 StreamBuilder?
    【解决方案2】:

    我用这个和rxdart:

    Rx.combineLatest2(behaviorSubject1, behaviorSubject2, (String mail, String subject) {
          return (mail.isNotEmpty && subject.isNotEmpty);
        }).listen((event) {
          event ? _enableButton.add(true) : _enableButton.add(false);
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 2020-03-20
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      相关资源
      最近更新 更多