Flutter页面打开时无法触发Bloc事件加载列表数据如何解决
Flutter Bloc页面初始化自动请求数据修复方案
核心问题原因
你当前代码无法触发初始化事件的核心原因是Bloc的注册时序和事件触发顺序错了:
- 你把
BlocProvider写在当前组件的build方法里,而initState的执行时机早于build方法 - 执行
initState里的context.read<WorkOrderBloc>()时,WorkOrderBloc还没有被注册到当前组件的上下文里,自然触发事件没有任何响应
其他存在的问题
- 你自己维护的
workOrderList声明为late但没有初始值,接口请求完成前访问会抛出空安全异常 - 独立的顶层方法
_myListView无法直接访问State类里的私有变量workOrderList - 使用Bloc的情况下没必要手动调用
setState存列表数据,直接从Bloc的State里取数据即可 - Checkbox的选中状态写在build方法里,每次页面刷新都会重置为false,且
setState的语法存在错误
修复后完整代码
class OrderListWidget extends StatefulWidget { const OrderListWidget({Key? key}) : super(key: key); @override _OrderListWidgetState createState() => _OrderListWidgetState(); } class _OrderListWidgetState extends State<OrderListWidget> { // 存储列表选中状态,不需要存在Bloc里的话可以本地维护 final List<bool> selectedList = []; @override Widget build(BuildContext context) { return BlocProvider( // 创建Bloc之后直接触发初始化请求事件,不需要依赖initState触发 create: (context) => WorkOrderBloc( workOrderRepo: context.read<WorkOrderRepository>(), type: WorkOrderType.mt )..add(WorkOrderListing(orderType: WorkOrderType.mt)), child: BlocListener<WorkOrderBloc, WorkOrderState>( listener: (context, state) { final formStatus = state.formStatus; if (formStatus is FormSubmitting) { LoadingDialog.openLoadingDialog(context, 'Please Wait'); } else { if (formStatus is! InitialFormStatus) { LoadingDialog.closeLoadingDialog(context); } if (formStatus is SubmissionFailed) { SnackbarWidget.show(context, formStatus.exception.toString(), Colors.red); } if (formStatus is SubmissionSuccess) { // 初始化选中状态列表 selectedList.clear(); selectedList.addAll(List.filled(state.workOrderList?.length ?? 0, false)); } } }, child: BlocBuilder<WorkOrderBloc, WorkOrderState>( builder: (context, state) { // 直接从BlocState里取列表,不用自己额外维护变量 final workOrderList = state.workOrderList; // 处理不同状态的页面渲染 if (state.formStatus is FormSubmitting) { return const Center(child: CircularProgressIndicator()); } if (workOrderList == null || workOrderList.isEmpty) { return const Center(child: Text('暂无工单数据')); } return _myListView(context, workOrderList); }, ), ), ); } // 改成内部方法,把列表数据作为参数传入 Widget _myListView(BuildContext context, List<WorkOrder> workOrderList) { return ListView.builder( itemCount: workOrderList.length, itemBuilder: (context, index) { return Card( child: CheckboxListTile( value: selectedList[index], onChanged: (value) { // 修正setState语法 setState(() { selectedList[index] = value!; }); }, title: Text(workOrderList[index].Name), ), ); }, ); } }
内容的提问来源于stack exchange,提问作者OguzKaanAkyalcin
相关产品推荐
相关产品推荐

