如何从Stream <List>方法返回列表?颤抖

时间:2020-03-09 00:57:08

标签: flutter firebase-realtime-database stream

我对Flutter还是很陌生,我使用flutter_bloc进行状态管理。 在bloc中,我正在侦听存储库方法Stream<List<UserAlert>> alerts()。在这种方法中,我同时监听了Firebase实时数据库节点上的.onChildAdded.onChildRemoved事件,并更新了本地List<UserAlert> alerts,但是更新后我没有成功返回它,所以我在Bloc侦听器上获取空值。 NoSuchMethodError: The method 'listen' was called on null.之所以选择手动管理它,是因为我不想在每次更改时都下载整个节点,因为它在听.onValue时会发生。我在两个Firebase快照范围内都尝试了return alerts as Stream<List<UserAlert>>,但遇到类型转换错误。 我在每个作用域内都尝试了Stream.value(alerts),并尝试了该方法的最后一步,但仍然返回null。 如何获得alerts作为流返回? 非常感谢您的帮助。

存储库方法:

Stream<List<UserAlert>> alerts() {
    print('alerts() called');
    Stream<List<UserAlert>> alertStream;

    List<UserAlert> alerts = [];
    // Option 2  return a list manually updated by two different events: More complicated but very efficient(bandwidth), lowest data consuming = Lowest Firebase bill.
    // returns one event per node record at app start and only new afterwards

    _alertSubscription = _databaseReference.onChildAdded.listen((Event event) {
      print(' observer .childAdded: added alert is : ${event.snapshot.value}');
      UserAlert userAlert = UserAlert.fromSnapshot(event.snapshot);
      alerts.add(userAlert);
//      alertStream = Stream.value(alerts); // alerts as Stream<List<UserAlert>>;
//      return alerts;

      print(
          'observer .childAdded: alerts are: $alerts and total alerts are ${alerts.length}');
    });

    // returns one event per node removed record
    _alertSubscription =
        _databaseReference.onChildRemoved.listen((Event event) {
      print(
          'observer .childRemoved: removed alert is : ${event.snapshot.value}');
      int index = alerts.indexWhere(
          (userAlert) => userAlert.id.startsWith(event.snapshot.value['Id']));

      print('index to remove is: $index');
      alerts.removeAt(index);

//      return alerts;
      print(
          'observer .childRemoved: alerts after removing are: $alerts and total alerts are ${alerts.length}');
//      return alerts;
    });
//    yield* alertStream;
    Stream.value(alerts);
  }

Bloc侦听器:

Stream<AlertState> _mapLoadAlertToState() async* {
    _alertSubscription?.cancel();
    _alertSubscription = _alertRepository
        .alerts()
        .listen((alerts) => add(AlertsUpdated(alerts)));
////        (List<UserAlert> alerts) {
////      print('_mapLoadAlertToState() userAlterts are: $alerts');
////      add(AlertsUpdated(alerts));
//    });
  }

2 个答案:

答案 0 :(得分:0)

您可以使用sudo ./zigbeefirmwareupdate -f /path/to/firmware/file.bin -d /dev/cu.usbserial-Dxxxx语句返回流:

yield

答案 1 :(得分:0)

我改变了方法,现在我可以像以前方法一样从firebase获取数据。 我决定将存储库方法分为两种不同的方法,这些方法将流转换为Stream<UserAlert

Stream<UserAlert> addedAlert() {
    print('addedAlert() called');
    handleData(Event event, EventSink<UserAlert> sink) =>
        sink.add(UserAlert.fromSnapshot(event.snapshot));

    final transformer = StreamTransformer<Event, UserAlert>.fromHandlers(
        handleData: handleData);

    return _databaseReference.onChildAdded.transform(transformer);
  }

  Stream<UserAlert> removedAlert() {
    print('removedAlert() called');
    handleData(Event event, EventSink<UserAlert> sink) =>
        sink.add(UserAlert.fromSnapshot(event.snapshot));

    final transformer = StreamTransformer<Event, UserAlert>.fromHandlers(
        handleData: handleData);

    return _databaseReference.onChildRemoved.transform(transformer);
  }

并处理bloc方法中对List<UserAlert>的添加和删除:

Stream<AlertState> _mapLoadAlertToState() async* {

    _addedAlertStreamSubcription =
        _alertRepository.addedAlert().listen((UserAlert alert) {
      print('received snapshot is:$alert.'); // prints null
      alerts.add(alert);
      print(
          'observer .childAdded: added alert is :$alert, we have ${alerts.length} active alerts, active alerts are: $alerts');
      add(AlertsUpdated(alerts));
    });

    _removedAlertStreamSubscription =
        _alertRepository.removedAlert().listen((UserAlert alert) {
      int index =
          alerts.indexWhere((userAlert) => userAlert.id.startsWith(alert.id));

      print('index to remove is: $index');
      alerts.removeAt(index);
      print(
          'observer .childRemoved: removed alert is :$alert, we have ${alerts.length} active alerts, active alerts are: $alerts');
      add(AlertsUpdated(alerts));
    });
  }

AlertUpdated然后将触发:

Stream<AlertState> _mapAlertsUpdatedToState(AlertsUpdated alert) async* {
    print(
        '_mapAlertsUpdatedToState() called, alerts are: ${alert.alerts} ');
    yield AlertLoaded(alert.alerts);
  } 

_mapAlertsUpdatedToState的打印显示正确的列表,但是来自BlocListener的打印仅显示一次,并且列表中只有一个值。

BlocListener<AlertBloc, AlertState>(
            listener: (BuildContext context, AlertState state) {
          if (state is AlertLoaded) {
            List<UserAlert> userAlerts = (state).alerts;
            print(
                'AlertListener userAlerts are: $userAlerts and total alerts are : ${userAlerts.length}');
          }
        }),

这可以通过使AlertState类不扩展Equatable来解决,因为它会比较先前状态和新状态并发现它们相同。 非常感谢。