使用flutter_bloc触发删除事件时如何刷新页面并重调用数据API
核心问题原因
- 删除操作成功后仅更新了服务端/数据库数据,Bloc内存中存储的
oldAlertModel列表没有同步更新,因此Bloc状态刷新时渲染的还是旧数据 - 你使用全局变量存储列表数据,子组件没有主动监听Bloc状态变更,无法拿到最新的列表数据
解决方案
按以下步骤调整即可实现删除后列表自动更新:
1. 调整Bloc删除逻辑,同步更新本地列表
在AlertBloc处理DeleteAlert事件的逻辑中,删除接口调用成功后直接移除内存列表中对应条目,再抛出成功状态:
on<DeleteAlert>((event, emit) async { emit(state.copyWith(alertStatus: AlertStatus.deletionAlert)); try { // 保留原有删除接口/数据库操作逻辑 await deleteAlertRequest(event.alertId); // 新增:本地移除已删除的条目 oldAlertModel.removeWhere((item) => item.alertId.toString() == event.alertId); emit(state.copyWith(alertStatus: AlertStatus.deletedAlert)); } catch(e) { emit(state.copyWith( alertStatus: AlertStatus.deletionAlertFailed, res: {"message": e.toString()} )); } });
如果业务要求删除后必须重新拉取全量最新数据,不需要本地修改列表,可在删除成功后直接触发拉取列表事件:
// 替换上面的本地移除逻辑,直接触发重新拉取 add(GetOldAlerts());
2. 废弃全局recordings变量,通过参数传递列表数据
不再使用全局变量存储列表,避免数据不同步:
// 修改_bodyForm方法,接收列表参数并传递给子组件 _bodyForm(AlertState state, List<AlertData> recordings){ return Stack( children: [ _RecordingsForm(recordings: recordings), state.alertStatus == AlertStatus.deletionAlert ? const _DeletionProcessBar() : const SizedBox() ], ); } // 修改BlocBuilder中的调用逻辑,直接获取最新列表传递 if (state.alertStatus == AlertStatus.gotOldAlerts || state.alertStatus == AlertStatus.deletedAlert || state.alertStatus == AlertStatus.deletionAlert) { final recordings = context.read<AlertBloc>().oldAlertModel; return _bodyForm(state, recordings); }
3. 调整列表子组件,使用传入的列表数据渲染
修改_RecordingsForm组件,接收父组件传入的最新列表:
class _RecordingsForm extends StatefulWidget { final List<AlertData> recordings; const _RecordingsForm({super.key, required this.recordings}); @override __RecordingsFormState createState() => __RecordingsFormState(); } class __RecordingsFormState extends State<_RecordingsForm> { @override Widget build(BuildContext context) { return ListView.builder( itemCount: widget.recordings.length, itemBuilder: (context, index) { final currentItem = widget.recordings[index]; return ListTile( trailing: currentItem.isPlaying ? Image.asset(PLAYING_ASSET, height: 20, width: 20) : PopupMenuButton( elevation: 3, child: Image.asset(VERTICAL_MENU_ASSET, height: 20, width: 20), itemBuilder: (_) => [ PopupMenuItem( value: "DELETE", height: 10, child: Row( children: [ const Text("DELETE", style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold)), const SizedBox(width: 4), Image.asset(DELETE_ASSET, height: 13, width: 13), ], ), ) ], onSelected: (val) => context.read<AlertBloc>().add( DeleteAlert(currentItem.alertId.toString()) ), ), // 其余列表项配置保持不变 contentPadding: ..., leading: ..., title: ... ); } ); } }
内容的提问来源于stack exchange,提问作者Shruti Ramnandan Sharma
相关产品推荐
相关产品推荐

