我正在尝试在我的应用程序中使用 flutter bloc 模式。它使用 quick_blue 库来扫描 BLE 设备。 QuickBlue 提供带有扫描结果的流。 我的目标是用一个事件开始扫描(每次找到设备时发出新状态)并用另一事件停止扫描。
问题:我很困惑如何取消活动扫描事件。由于 scanResultStream 来自第 3 方库,我无法控制它。因此,emit.onEach 保持活动状态,直到另一个 StartScanEvent 触发(感谢 restartable())。
我查看了带有流的flutter bloc example,但是流是在应用程序内部创建的,因此用户可以完全控制它。 我很感激任何建议。
这是我的集团代码:
class BLEBloc extends Bloc<BLEEvent, BLEState> {
final List<BlueScanResult> scanResult = [];
final Stream scanStream = QuickBlue.scanResultStream;
BLEBloc() : super(BLEInitState()) {
on<StartScanEvent>((event, emit) async {
QuickBlue.startScan();
scanResult.clear();
// want to cancel this
await emit.onEach(
scanStream,
onData: (data) {
scanResult.add(data);
emit(DeviceFoundState(scanResult));
},
);
print("finished"); // finishes only on next StartScanEvent
}, transformer: restartable());
on<StopScanEvent>(
(event, emit) {
QuickBlue.stopScan();
emit(ScanFinishedState());
},
);
}
}
我建议使用
Stream.listen
,这样您就可以随时取消订阅。
class BLEBloc extends Bloc<BLEEvent, BLEState> {
final List<BlueScanResult> scanResult = [];
final Stream scanStream = QuickBlue.scanResultStream;
StreamSubscription? _sub;
BLEBloc() : super(BLEInitState()) {
on<StartScanEvent>((event, emit) async {
QuickBlue.startScan();
scanResult.clear();
_sub = scanStream.listen((data) {
scanResult.add(data);
emit(DeviceFoundState(scanResult));
});
}, transformer: restartable());
on<StopScanEvent>(
(event, emit) {
_sub?.cancel();
QuickBlue.stopScan();
emit(ScanFinishedState());
},
);
}
}
我想我已经找到解决方案了。
流订阅在监听流时应该触发不同的事件。 这个新事件应该发出状态。
这是示例代码:
class BBloc extends Bloc<MyEvent, MyState> {
var counterStream = Stream<int>.periodic(const Duration(seconds: 1), (x) => x)
.asBroadcastStream();
StreamSubscription? _subscription;
BBloc() : super(MyInitalState()) {
on<PressedEvent>((event, emit) {
_handlePressedEvent(event, emit);
});
on<SubEvent>(
(event, emit) {
emit(StateA());
},
);
}
void _handlePressedEvent(PressedEvent event, Emitter<MyState> emit) {
// Cancel previous subscription if it exists
_subscription?.cancel();
// Start a new subscription
_subscription = counterStream.listen((data) {
print(data);
add(SubEvent());
});
}
}