Flutter Bloc疑问:如何传递事件通知UI更新已选图片
问题描述
我创建了HomeworkBloc类,用于从相册获取图片并渲染至UI。流程是通过eventImageSink传递事件,_eventImageStream监听事件后将图片添加至_stateImageSink,再借助stateImageStream配合StreamBuilder在UI中渲染图片。但我困惑的是,选择新图片后,如何向eventImageStream传递事件以触发UI更新?
相关代码
HomeworkBloc 代码
enum GetImage { fetchImage } class HomeworkBloc { final ImagePicker imagePicker = ImagePicker(); List<XFile>? selectedImages; List<XFile>? pickedImages; final _imageStateStreamController = StreamController<List<XFile>>.broadcast(); StreamSink<List<XFile>> get _stateImageSink => _imageStateStreamController.sink; Stream<List<XFile>> get stateImageStream => _imageStateStreamController.stream; final _imageEventStreamController = StreamController<GetImage>(); StreamSink<GetImage> get eventImageSink => _imageEventStreamController.sink; Stream<GetImage> get _eventImageStream => _imageEventStreamController.stream; HomeworkBloc() { _eventImageStream.listen((event) async { if (event == GetImage.fetchImage) { if (pickedImages != null) { _stateImageSink.add(pickedImages!); } } }); } void selectImage() async { selectedImages = await imagePicker.pickMultiImage( maxHeight: 800, maxWidth: 800, imageQuality: 100); List<XFile> temp = pickedImages ?? []; pickedImages = selectedImages; pickedImages?.addAll(temp); } }
StreamBuilder 代码
StreamBuilder<List<XFile>?>( stream: hB.stateImageStream, builder: (ctx, snapShot) { if (!snapShot.hasData) { return const Center( child: Text("no Data"), ); } else if (snapShot.hasData) { return GridView.builder( shrinkWrap: true, itemCount: snapShot.data!.length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5), itemBuilder: (ctx, i) { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10)), child: Stack( children: [ Image.file(File(snapShot.data![i].path)), Stack( children: [ Container( height: 40, width: 40, color: Colors.red.withOpacity(0.3), child: IconButton( onPressed: () { setState(() { snapShot.data!.removeAt(i); }); }, icon: const Icon(Icons.delete_forever, color: Colors.white)), ) ], ), ], )); }); } else { return Container(); } }, ))
解决方案
1. 修正selectImage方法逻辑并触发事件
当前selectImage存在逻辑错误(会覆盖原有图片列表),且缺少触发UI更新的事件传递。修改后的方法如下:
void selectImage() async { selectedImages = await imagePicker.pickMultiImage( maxHeight: 800, maxWidth: 800, imageQuality: 100); // 仅在选到图片时更新列表并触发事件 if (selectedImages != null && selectedImages!.isNotEmpty) { // 初始化空列表(若pickedImages未创建) pickedImages ??= []; // 将新选图片追加到原有列表 pickedImages!.addAll(selectedImages!); // 向事件流发送fetchImage事件,触发UI更新 eventImageSink.add(GetImage.fetchImage); } }
2. 修复StreamBuilder中的删除逻辑(额外优化)
直接修改snapShot.data不符合数据流规范,需通过Bloc处理删除操作:
- 在
HomeworkBloc中添加删除方法:
void deleteImage(int index) { if (pickedImages != null && index >= 0 && index < pickedImages!.length) { pickedImages!.removeAt(index); // 删除后触发事件更新UI eventImageSink.add(GetImage.fetchImage); } }
- 修改StreamBuilder中删除按钮的点击事件:
onPressed: () { hB.deleteImage(i); },
内容的提问来源于stack exchange,提问作者saurav
相关产品推荐
相关产品推荐

