带有流的 Flutter 块

问题描述 投票:0回答:2

我正在尝试在我的应用程序中使用 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());
    },
  );
}
}
flutter dart stream bloc
2个回答
0
投票

我建议使用

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());
      },
    );
  }
}

0
投票

我想我已经找到解决方案了。

流订阅在监听流时应该触发不同的事件。 这个新事件应该发出状态。

这是示例代码:

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());
    });
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.