如何在一个块中收听多个流订阅?

Posted

技术标签:

【中文标题】如何在一个块中收听多个流订阅?【英文标题】:How to listen to multiple stream subscriptions in a bloc? 【发布时间】:2021-07-17 18:56:29 【问题描述】:

我正在尝试创建一个依赖于其他两个集团的集团。例如,我有Bloc C,它依赖于Bloc ABloc 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。我在下一个post 中找到了有关该错误的信息。

我了解错误正在发生,因为流一次只能听一个 bloc,而不能听多个 bloc。就我而言,当我尝试收听blocB 时,流已经在收听blocA。但是,我不确定如何解决此问题。

我将非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

您必须将两个流合并为一个并根据事件类型采取行动:

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));
    
  
)

【讨论】:

【参考方案2】:

我已经实现了事件总线模式来在块之间进行通信。这种方法的优点是您的块实例不会相互耦合,因此您不需要 实例化或注入他们的实例Manage Global Events by bloc

【讨论】:

以上是关于如何在一个块中收听多个流订阅?的主要内容,如果未能解决你的问题,请参考以下文章

我如何在 Angular 应用程序中订阅/收听 chrome 推送通知

如何在 Google Cloud App Engine 上使用 PubSub 创建订阅者,该订阅者通过 Publisher 从 Google Cloud App Engine Flex 收听消息?

flutter - 如何在 dart/flutter 中收听流值

如何在 Dart 的流构建器中切换我正在收听的流?

如何在 Spring Boot 中收听流式 API?

Firebase:如何停止收听快照