将多个BehaviorSubject流合并为一个?

时间:2019-04-16 04:54:08

标签: dart rxdart

我的目标是使用多个流而不必嵌套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一次就可以对该组合流进行流处理。

2 个答案:

答案 0 :(得分:1)

您可以检查combineLatest()类的Observable方法。它通过使用合并器功能将给定的Streams合并为一个Observable序列,这样除非所有Streams都至少发射了一项,否则不会发射得到的Observable。

有一堆combineLatest()方法。但是由于您有3个流,因此可以使用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<String, dynamic>' and add the Stream values into the地图if you want to access the data from all three streams. And in your StreamBuilder`小部件,您可以使用--

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

希望这会有所帮助!

答案 1 :(得分:0)

我将它与 rxdart 一起使用:

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