繁体   English   中英

Flutter Bloc to Bloc Communication:如何在初始收听广播流时接收数据?

[英]Flutter Bloc to Bloc Communication: How to receive data on initial listen to broadcast stream?

问题摘要:当我创建一个新的 bloc 时,我试图从 BlocA 的 StateA 中获取一个列表。

简化背景:我有一个总体块 (BlocA),它在此问题的上下文中始终处于活动状态,以及 2 个屏幕,每个屏幕都有一个相应的块 (BlocB 和 BlocC),在路由到其关联屏幕时创建并在路由离开时关闭从其关联的屏幕。 每次创建一个新的 bloc 时,它都需要从 BlocA 的状态中获取其数据。 用户可能会在屏幕之间来回移动。

我尝试了什么:我在 BlocA 中创建了流控制器,通过 getter 将相关数据流式传输到每个 bloc。 起初,我尝试了一个正常的(单监听器)流,它最初运行良好。 但是,当路由离开然后返回屏幕时,使用 getter 重新订阅同一流时会引发错误。 然后我将流控制器实例化为广播流StreamController.broadcast() 那么问题是,当订阅流时,订阅流时不会像普通流一样传递任何数据,当我尝试在广播构造函数中实现 onListen 回调时(将事件添加到接收器)它给出我的错误The instance member '_aStream' can't be accessed in an initializer 状态出现类似的错误。 见下文:

... _aStream = StreamController.broadcast(onListen: () {return _aStream.add(state.TypeX)})

简化示例代码:

class BlocA extends Bloc<BlocAEvent, BlocAState> {
  BlocA() : super(BlocAState()) {
    on<EventA>(_onevent);
  }

  final StreamController<TypeX> _aStream = StreamController.broadcast();
  Stream<TypeX> get aStream => _aStream.stream;

  final StreamController<TypeY> _bStream = StreamController.broadcast();
  Stream<TypeY> get bStream => _bStream.stream;

  ...
  
  // sink.add()'s are implemented in events
}

class BlocB extends Bloc<BlocBEvent, BlocBState> {
  BlocB({required this.blocA}) : super(BlocBState()) {
    on<EventB>(_onEventB);
    blocASubscription = blocA.aStream.listen((stream) {
      if (stream != state.fieldX) {
        add(EventB(fieldX: stream));
      }
    });
  }

  final BlocA blocA
  late final StreamSubscription blocASubscription;


  FutureOr<void> _onEventB(EventB event, Emitter<BlocBState> emit) {
    emit(state.copyWith(fieldX: event.fieldX));
  }
}
    
class BlocC extends Bloc<BlocCEvent, BlocCState> {
  // similar to BlocB
}

您不需要流,因为 bloc underhood 还在流中。 你可以通过事件和状态发送你想要的一切。 查看 Angelov 的库https://bloclibrary.dev/#/

我最终还是使用了示例代码中使用的流控制器,但是为 BlocA 创建了一个新事件,当用户在屏幕之间切换并将适当的状态数据下沉到流中时,它会被触发。 该事件带有一个索引字段来指示路由到的屏幕。 事件的索引对应于 navBar 索引。

事件处理实现如下所示:

  FutureOr<void> _onScreenChanged(
    ScreenChanged event,
    Emitter<BlocAState> emit,
  ) async {
    switch (event.index) {
      case 0:
        _aStream.sink.add(state.fieldX);
        break;
      case 1:
        _bStream.sink.add(state.fieldY);
        break;
      default:
    }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM