Как слушать подписки на несколько потоков в блоке?

Я пытаюсь создать блок, который зависит от двух других блоков. Например, у меня есть Bloc C, который зависит от Bloc A и Bloc B. Я пытаюсь сделать что-то вроде следующего, используя flutter_bloc, чтобы добиться этого:

class BlocC
    extends Bloc< BlocCEvent, BlocCState> {
  final BlocA blocA;
  final BlocC blocB;

  StreamSubscription blocASubscription;
  StreamSubscription blocBSubscription;

  BlocC({
    @required this.blocA,
    @required this.blocB,
  }) : super((blocA.state is blocALoaded &&
                blocB.state is blocBLoaded)
            ? BlocCLoaded(
                blocA: (blocA.state as blocALoaded).arrayFromBlocA,
                blocB:
                    (blocB.state as blocBLoaded).arrayFromBlocB,
              )
            : BlocCLoading()) {
              
    blocASubscription = blocA.stream.listen((state) {
      if (state is blocALoaded) {
        add(BlocAUpdated((blocA.state as blocALoaded).arrayFromBlocA));
      }
    });

    blocBSubscription = blocB.stream.listen((state) {
      if (state is BlocBLoaded) {
        add(BlocBUpdated((blocB.state as BlocBLoaded).arrayFromBlocB));
      }
    });
  }

  ...

  @override
  Future<void> close() {
    blocASubscription.cancel();
    BlocBSubscription.cancel();
    return super.close();
  }
}

Проблема в том, что я получаю следующую ошибку: Bad state: Stream has already been listened to. Я нашел информацию об этой ошибке в следующем сообщении. .

Я понимаю, что ошибка возникает из-за того, что поток может слушать только один блок за раз, а не несколько. В моем случае поток уже слушает blocA, когда я пытаюсь прослушать blocB. Однако я не уверен, как решить эту проблему.

Я буду очень признателен за любую помощь в этом.


person Yunet Luis Ruíz    schedule 23.04.2021    source источник


Ответы (2)


Вы должны объединить два потока в один и действовать в зависимости от типа события:

import 'package:async/async.dart' show StreamGroup;

//...

final blocAStream = blocA.stream;
final blocBStream = blocB.stream;
var blocAandBStreams = StreamGroup.merge([blocAStream, blocBStream]);

blocAandBStream.listen((event){
  if(event is BlocAState){
    if (event is blocALoaded) { //<-- for readability
      add(BlocAUpdated((blocA.state as blocALoaded).arrayFromBlocA));
    }
  }else if(event is BlocBState){
    if (event is BlocBLoaded) {//<-- for readability
      add(BlocBUpdated((blocB.state as BlocBLoaded).arrayFromBlocB));
    }
  }
})

person Younss AIT MOU    schedule 28.04.2021

Я реализовал шаблон шины событий для связи между блоками. Преимущество этого подхода заключается в том, что ваши экземпляры блоков не связаны друг с другом, поэтому вам не нужно создавать или вводить их экземпляры Управление глобальными событиями по блокам

person Sergey Zhukov    schedule 05.05.2021