Flutter Bloc 到 Bloc 通信:如何在初始收听广播流时接收数据?
Flutter Bloc to Bloc Communication: How to receive data on initial listen to broadcast stream?
问题总结:
当我创建一个新的 bloc 时,我正在尝试从 BlocA 的 StateA 获取列表。
简化背景:
我有一个总体集团 (BlocA),它在这个问题的上下文中始终处于活动状态,并且有 2 个屏幕,每个屏幕都有一个相应的集团(BlocB 和 BlocC),当路由到其关联屏幕时创建并在远离其关联屏幕时关闭屏幕。每次创建新区块时,它都需要从 BlocA 的状态中获取数据。用户可能会在屏幕之间来回移动。
我尝试了什么:
我在 BlocA 中创建了流控制器,它通过 getter 将相关数据流式传输到每个块。起初,我尝试了一个正常的(单个监听器)流,最初运行良好。但是,当路由离开然后返回屏幕时,它会在使用 getter 重新订阅同一流时抛出错误。然后我将流控制器实例化为广播流 StreamController.broadcast()
。那么问题是,当订阅流时,没有数据像普通流一样在订阅流时传递,当我尝试在广播构造函数中实现 onListen 回调(向接收器添加事件)时,它给出我的错误 The instance member '_aStream' can't be accessed in an initializer
。 state 也会出现类似的错误。见下文:
... _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 创建了一个新事件,当用户在屏幕之间切换时触发该事件并将适当的状态数据汇入流中。该事件带有一个索引字段以指示路由到的屏幕。该事件的索引对应于导航栏索引。
事件处理实现如下所示:
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:
}
}
问题总结: 当我创建一个新的 bloc 时,我正在尝试从 BlocA 的 StateA 获取列表。
简化背景: 我有一个总体集团 (BlocA),它在这个问题的上下文中始终处于活动状态,并且有 2 个屏幕,每个屏幕都有一个相应的集团(BlocB 和 BlocC),当路由到其关联屏幕时创建并在远离其关联屏幕时关闭屏幕。每次创建新区块时,它都需要从 BlocA 的状态中获取数据。用户可能会在屏幕之间来回移动。
我尝试了什么:
我在 BlocA 中创建了流控制器,它通过 getter 将相关数据流式传输到每个块。起初,我尝试了一个正常的(单个监听器)流,最初运行良好。但是,当路由离开然后返回屏幕时,它会在使用 getter 重新订阅同一流时抛出错误。然后我将流控制器实例化为广播流 StreamController.broadcast()
。那么问题是,当订阅流时,没有数据像普通流一样在订阅流时传递,当我尝试在广播构造函数中实现 onListen 回调(向接收器添加事件)时,它给出我的错误 The instance member '_aStream' can't be accessed in an initializer
。 state 也会出现类似的错误。见下文:
... _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 创建了一个新事件,当用户在屏幕之间切换时触发该事件并将适当的状态数据汇入流中。该事件带有一个索引字段以指示路由到的屏幕。该事件的索引对应于导航栏索引。
事件处理实现如下所示:
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:
}
}