Flutter对话框更新数据:调用_issueItem()后ListView不刷新如何解决
问题根因
- 你调用的
setState是父组件的实例,和StatefulBuilder内部暴露的setState不是同一个实例,无法触发StatefulBuilder的局部刷新 getIssuedItems方法返回的是FutureBuilder组件,你在setState中直接调用该方法没有将返回的新组件挂载到视图树中,无任何实际效果- 列表的数据源没有作为状态变量存放在State中,即使拉取到最新数据,也无法触发视图更新
修复方案
步骤1:在当前页面State类中定义状态变量
// 存已发放物品列表 List<IssuedItems>? _issuedItemsList; // 存列表加载状态 bool _isLoadingIssuedItems = false;
步骤2:改造拉取数据的方法,不再返回组件,直接更新状态
Future<void> fetchIssuedItems(String brigadeNumber) async { setState(() { _isLoadingIssuedItems = true; }); var data = {'brigade': brigadeNumber}; try { var response = await ServerSideApi.create(UserState.getIP()!, 6).getIssuedItems(data); if (response.body != null) { setState(() { _issuedItemsList = response.body!; }); } } catch(e) { // 按需添加异常处理逻辑 } finally { setState(() { _isLoadingIssuedItems = false; }); } }
步骤3:改造列表渲染逻辑,直接绑定状态变量
把原来调用getIssuedItems(brigadeNumber)的位置替换成下面的代码:
Widget _buildIssuedList() { if (_isLoadingIssuedItems) { return const Center(child: CircularProgressIndicator()); } if (_issuedItemsList == null || _issuedItemsList!.isEmpty) { return const Center(child: Text('Нет выданных товаров')); } // 如果列表内部没有需要单独修改的状态,可以直接删掉StatefulBuilder return ListView.separated( itemCount: _issuedItemsList!.length, separatorBuilder: (context, index) => const Divider(), itemBuilder: (context, index) { IssuedItems item = _issuedItemsList![index]; Uint8List bytes = const Base64Decoder().convert(item.photo.toString()); return GestureDetector( onTap: () => log(item.item), child: ListTile( title: Text('${item.item}, ${item.count} ${item.countOption}, ${item.date}'), leading: Container( height: 7.h, width: 7.w, decoration: BoxDecoration( image: DecorationImage(image: Image.memory(bytes).image) ), ), ), ); }, ); }
步骤4:修改发放成功后的回调逻辑
case 'item_issued_successfully': _showToast(7); Navigator.pop(context); // 直接调用拉取方法,方法内部会自动更新状态触发列表刷新 fetchIssuedItems(brigadeNumber); break;
额外优化建议
如果你的列表只是做展示用,没有在列表项内部修改状态的需求,完全可以去掉StatefulBuilder嵌套,减少不必要的组件层级。
内容的提问来源于stack exchange,提问作者user16772576
相关产品推荐
相关产品推荐

