【发布时间】:2021-01-29 14:01:01
【问题描述】:
我有一个由集团状态控制的小部件。作为开始,一个 url 列表被传递给用于创建初始网格的小部件。然后,一旦必须添加或删除 url,就会调用 bloc 事件来更新列表并产生新的状态。然而,我的问题是,当一个项目被删除时,打印到屏幕上的列表是正确的(删除了项目),但 gridview 似乎只删除了最后一个图像而不是删除的图像。我在这里做错了什么?
Related question(我确实从 Gridview.count 更改为 Gridview.builder),但无济于事。
小部件:
class ItemImageGrid extends StatelessWidget {
final List<String> urls;
const ItemImageGrid({Key key, this.urls }) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: BlocBuilder<ItemGridBloc, ItemGridState>(
builder: (context, state) {
if(state is ItemGridInitialState){
print("state is ItemGridInitialState");
return _showCarouselAndStartLoading(context);
}else if(state is ImagesUpdatedState){
print("state is ImagesUpdatedState");
return _showGrid(context, state.urls);
}
return Center(child: CircularProgressIndicator());
},
),
);
}
Widget _showCarouselAndStartLoading(BuildContext context){
BlocProvider.of<ItemGridBloc>(context).add( // add or dispatch??? try both to see difference - seems dispatch cannot be used here...
LoadImageEvent(urls),
);
return Center(child: CircularProgressIndicator());
}
Widget _showGrid(BuildContext context, List<String> urls) {
if(urls.isEmpty){
return Center(
child: Text("No photos yet")
);
}
return GridView.builder(
itemCount: urls.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
// You must use the GridDelegate to specify row item count
// and spacing between items
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
// childAspectRatio: 1.0,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0,
),
itemBuilder: (BuildContext context, int index) {
return BlocProvider(
create: (context) => CachedImageBloc( ),
child: GestureDetector(
onTap: () => {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context2) {
// List<String> clonedList;
return BlocProvider(
create: (context) => new CachedImageBloc( ),
child: new BasicImagePreview(
imageFilePath: urls[index],
// bloc: BlocProvider.of<InspectionItemAddEditBloc>(context),
// image_paths: imagePaths,
onDelete: () =>{
BlocProvider.of<ItemGridBloc>(context).add(ImageRemovedEvent( urls[index])),
},
),
);
}))
},
child: LocalImageViewer(
url: urls[index],
errorAssetPath: 'assets/error_loading.png' ),
),
);
},
);
}
}
集团:
class ItemGridBloc extends Bloc<ItemGridEvent, ItemGridState> {
List<String> urls;
ItemGridBloc();
@override
Stream<ItemGridState> mapEventToState(
ItemGridEvent event,
) async* {
print('event = $event');
if(event is ImageAddedEvent){
yield* _mapImageAddedEventToState(event);
}
else if(event is ImageRemovedEvent){
yield* _mapImageRemovedEventToState(event);
} else if(event is LoadImageEvent){
yield* _mapLoadImageEventToState(event);
}
}
@override
ItemGridState get initialState => ItemGridInitialState();
Stream<ItemGridState> _mapImageAddedEventToState(ImageAddedEvent event) async*{
urls.add(event.url);
yield ImagesUpdatedState(List.of(urls));
}
Stream<ItemGridState>_mapImageRemovedEventToState(ImageRemovedEvent event) async*{
print('urls b4 remove:');
urls.forEach((element) {print('$element');});
print('removing url: ${event.url}');
urls.remove(event.url);
print('urls after remove:');
urls.forEach((element) {print('$element');});
yield ImagesUpdatedState(urls);
}
Stream<ItemGridState> _mapLoadImageEventToState(LoadImageEvent event) async*{
urls = List.of(event.urls);
yield ImagesUpdatedState(event.urls);
}
}
事件类:
abstract class ItemGridEvent extends Equatable {
const ItemGridEvent();
}
class ImageAddedEvent extends ItemGridEvent{
final String url;
ImageAddedEvent(this.url);
@override
List<Object> get props => [url];
}
class LoadImageEvent extends ItemGridEvent{
final List<String> urls;
LoadImageEvent(this.urls);
@override
List<Object> get props => [urls];
}
class ImageRemovedEvent extends ItemGridEvent{
final String url;
ImageRemovedEvent(this.url);
@override
List<Object> get props => [url];
}
状态类:
abstract class ItemGridState extends Equatable {
const ItemGridState();
}
class ItemGridInitialState extends ItemGridState {
@override
List<Object> get props => [];
}
class ImagesUpdatedState extends ItemGridState {
final List<String> urls;
ImagesUpdatedState(this.urls);
@override
List<Object> get props => [urls];
}
【问题讨论】:
-
您需要将更新后的 URL 传递给 ItemImageGrid() -- 这实际上是在渲染网格
-
@jitsm555 试过了,我注意到问题与我没有为小部件分配密钥有关。请参阅我的答案以获得进一步的解释。