我对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));
// });
}
答案 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来解决,因为它会比较先前状态和新状态并发现它们相同。
非常感谢。