它看起来像是程序块v0.11.2中的错误
我有以下事件/状态:
class DeleteReceipt extends ReceiptEvent {
final Receipt receipt;
DeleteReceipt(this.receipt) : super([receipt]);
}
class ReceiptDeleted extends ReceiptState {
final Receipt receipt;
ReceiptDeleted(this.receipt) : super();
}
和下面的代码块:
if (event is DeleteReceipt) {
var delReceipt = event.receipt;
await _receiptDao.delete(delReceipt);
print("deleting: " + delReceipt.snapshot.documentID);
yield ReceiptDeleted(delReceipt);
}
和我的小部件:
if (state is ReceiptDeleted) {
print("delete: "+state.receipt.snapshot.documentID);
receipts.delete(state.receipt);
}
当我这样做的时候:第一次得到:_receiptBloc.dispatch(DeleteReceipt(receipt));
:
I/flutter (28196): deleting: AzgAzcn5wRNFVd7NyZqQ
I/flutter (28196): delete: AzgAzcn5wRNFVd7NyZqQ
这是正确的,但当我第二次对不同的收据执行_receiptBloc.dispatch(DeleteReceipt(receipt));
时,我得到:
I/flutter (28196): deleting: d4oUjrGwHX1TvIDr9L2M
I/flutter (28196): delete: AzgAzcn5wRNFVd7NyZqQ
您可以看到,在第二次使用正确的值接收DeleteReceipt
事件,但是使用错误的值接收ReceiptDeleted
状态,然后它就像这样卡住了,它永远不会使用正确的值触发ReceiptDeleted
状态,只使用第一个值。
我的应用程序不是微不足道的,我在过去设置了很多事件和状态,它没有出现任何问题(除了这个,可能是与flutter bloc state not received相关的)
基本上,我让用户创建收据的照片,这些照片是持久的(使用bloc/firestore),我想让用户删除它们,所以当用户单击收据时,它会在一个新的屏幕中打开:
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return ReceiptDetailPage(widget.receipt);
},
),
当用户单击delete时,我会显示一个对话框,如果为OK
,则删除收据
var result = await showDialog(
context: context,
builder: (BuildContext dialogCtxt) {
// return object of type Dialog
return AlertDialog(
title: new Text(AppLocalizations.of(context).deleteReceiptQuestion),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text(AppLocalizations.of(context).cancel),
onPressed: () {
Navigator.of(dialogCtxt).pop("cancel");
},
),
new FlatButton(
child: new Text(AppLocalizations.of(context).ok),
onPressed: () {
Navigator.of(dialogCtxt).pop("OK");
},
),
],
);
},
);
if (result == 'OK') {
Navigator.of(context).pop();
_receiptBloc.dispatch(DeleteReceipt(receipt));
}
发布于 2020-01-07 13:33:54
解决方案:
添加状态/事件:
class EmptyState extends ReceiptState {}
class EmptyEvent extends ReceiptEvent {}
收到删除状态后,请执行以下操作:
if (state is ReceiptDeleted) {
print("delete: "+state.receipt.snapshot.documentID);
receipts.delete(state.receipt);
_receiptBloc.dispatch(EmptyEvent()); // add this line
}
并将此内容添加到您的区块中
if (event is EmptyEvent) {
yield EmptyState();
}
这将导致激发一个空事件和状态,并将清除问题
解释:我注意到,一旦我触发了一个状态,区块提供者就会在我每次更改屏幕时发送该状态,这很奇怪,因为应用程序多次收到Delete
状态。在我的例子中,这不是问题,因为代码将尝试删除已经删除的元素,并将静默失败:
void delete(Receipt receipt) {
try {
Receipt oldReceipt = receipts.firstWhere(
(r) => r.snapshot.documentID == receipt.snapshot.documentID);
receipts.remove(oldReceipt);
} catch (e) {
print(e);
}
}
注意:这似乎发生在应用程序正在触发的所有状态下,而不仅仅是Delete
状态
因此,我邀请如果我将触发一个空事件,它将清除旧的Delete
状态,并以某种方式修复该问题,而WALLA...
请注意,我并不需要在代码中的任何地方实际监听EmptyState
更多信息:
我意识到虽然bloc
似乎是松散的状态,但我的设计也是错误的,因为数据结构应该在bloc
中更新,一旦事件被接收,而不是在小部件中,当状态被接收时(或者在本例中没有接收,这会导致错误)
最初我使用bloc
和sembast
,但后来我想让数据与远程数据库同步,所以我用firestore
代替了sembast
。
但这会导致加载时间从零到超过2秒,这是一个问题,因为在原始设计中,我在每次更新时从数据库加载所有数据。
所以我试着分别更新store
和UI。我没有读取所有数据,而是在小部件中保留了一个列表,并在状态更改时更新小部件-每个更新/删除状态。
这是一个问题,因为许多状态都丢失了(特别是当用户单击fast时-这会导致许多事件/状态被触发)
所以我猜correct
的解决方案应该是在一个单独的服务中管理内存中的数据,并在收到事件时更新数据,然后从服务而不是存储中读取所有数据(如果可能)
https://stackoverflow.com/questions/59629235
复制