独立BLoC实例异常:表单清除时误删历史图片数据求助
问题原因分析
你的核心问题出在每次indexCubit触发BlocBuilder重建时,都会重复创建ShowImageCubit实例并添加到listCubit,同时重复添加空数组到listFiles,导致listCubit和listFiles的元素数量不断膨胀,且与listProduct的对应关系完全错乱:
- 当
indexCubit.change()触发重建时,List.generate(listProduct.length, ...)会循环执行listProduct.length次,每次都执行listCubit.add(showImageCubit)和listFiles.add(imageFiles),这会让listCubit的长度变成原长度 + listProduct.length,而非和listProduct保持一致的长度。 - 此时
ProductInput接收的bloc: listCubit[index]已经不是最初绑定的ShowImageCubit实例,而是某次重建时新增的空Cubit,所以显示的图片消失,看起来像是被"删除"了。 - 另外
ProductInput使用UniqueKey()会强制每次重建都销毁旧控件、创建新控件,进一步加剧状态丢失问题。
修复方案
1. 同步listProduct、listCubit、listFiles的创建与删除
不要在List.generate里动态创建Cubit和文件数组,而是在添加新商品表单时同步初始化对应的Cubit和空数组;删除时同步移除对应元素:
void addProduct(ModelProductOrder val) { listProduct.add(val); // 同步创建对应Cubit和空文件数组 listCubit.add(ShowImageCubit()); listFiles.add([]); indexCubit.change(Random().nextInt(100000)); }
2. 修改ListView的构建逻辑
在List.generate里直接使用已有的listCubit[index]和listFiles[index],不再重复创建和添加:
BlocBuilder( bloc: indexCubit, builder: (context, state) { return ListView( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, children: List.generate( listProduct.length, (index) { // 移除此处的Cubit和数组创建代码 return ProductInput( key: ValueKey(index), // 改用ValueKey(index),保证同index对应同控件 callBack: (val) { isUpdate = false; listProduct[index] = val; indexCubit.change(Random().nextInt(100000)); }, dataUpdate: listProduct[index], bloc: listCubit[index], // 直接使用已有的Cubit实例 onDelete: () { DialogItem.showMsg( context: context, title: 'Xác nhận xoá sản phẩm', msg: "Bạn có muốn xoá sản phẩm này?", onConfirm: () { listProduct.removeAt(index); listCubit.removeAt(index); listFiles.removeAt(index); indexCubit.change(Random().nextInt(100000)); Navigator.pop(context); }, ); }, listFiles: listFiles[index], // 直接使用已有的文件数组 ); }, ), ); }, ),
3. 确保clearInput只操作当前表单的Cubit
检查ProductInput内部的showImage是否是传入的widget.bloc实例,避免误操作其他表单的状态:
// 在ProductInput类中 ShowImageCubit get showImage => widget.bloc; void clearInput() { seriesCode.clear(); warrantyCode.clear(); showImage.clear(); // 仅操作当前表单绑定的Cubit,不会影响其他表单 }
4. 移除不必要的setState
删除操作里的空setState()可以移除,改用indexCubit.change()触发BlocBuilder重建即可,保持状态管理统一。
内容的提问来源于stack exchange,提问作者nghkh
相关产品推荐
相关产品推荐

