如何在同一块中等待多个块事件



我有一个包含多个事件的块。在这里,我加载类别和位置,并使用BlocListener等待。但我的条件显示循环进度指标工作不正确,负载类别和位置后也显示。在这种情况下,我怎样才能正确地使用bloc呢?

apiDataBloc.add(LoadCategoriesEvent());
apiDataBloc.add(LoadLocationsEvent());
------------------------
return BlocListener<ApiDataBloc, ApiDataState>(
listener: (context, state) {
if (state is CategoriesLoaded) {
categories = state.categories;
print("Categories loaded");
print(categories.length);
}
},
child: BlocListener<ApiDataBloc, ApiDataState>(
listener: (context, s) {
if (s is LocationsLoaded) {
locations = s.locations;
print("Locations loaded");
print(locations.length);
}
},
child: locations != null &&
categories != null &&
categories.length > 0 &&
locations.length > 0
? Container(child: Center(child: Text('Categories and locations loaded!')))
: Container(child: Center(child: CircularProgressIndicator())),
),
);

我也试过这样做,但不工作。

return BlocProvider<ApiDataBloc>(
create: (context) => apiDataBloc,
child: BlocBuilder<ApiDataBloc, ApiDataState>(
builder: (context, state) {
if (state is LocationsLoaded) {
print("Locations loaded");
locations = state.locations;
print(locations.length);
return BlocBuilder<ApiDataBloc, ApiDataState>(
builder: (context, s) {
if (s is CategoriesLoaded) {
print("Categories loaded");
categories = s.categories;
print(categories.length);
return Container(
child: Center(
child: Text('Categories and locations loaded!')));
}
return Container(
child: Center(child: CircularProgressIndicator()));
},
);
}
return Container(child: Center(child: CircularProgressIndicator()));
},
),
);

您应该创建一个状态DataLoaded有2个字段类别

像这样:

class DataLoaded extends ApiDataState {
const DataLoaded(
this.categories,
this.locations,
);
final List<Type> categories;
final List<Type> locations;
@override
String toString() => 'DataLoaded';
}
然后你需要从API中获取数据在ApiDataBloc类:
class ApiDataBloc extends Bloc<YourEventType, ApiDataState> {
ApiDataBloc() : super(YourInitialState());
@override
Stream<ApiDataState> mapEventToState(YourEventType event) async* {
if (event is YourFetchApiEvent) {
yield YourLoadingState();
final categories = await _fetchCategories();
final locations = await _fetchLocations();
yield DataLoaded(categories,locations);
}
}
}

,最后一步是BlocBuilder在您的小部件中:

return BlocProvider<ApiDataBloc>(
create: (context) => apiDataBloc,
child: BlocBuilder<ApiDataBloc, ApiDataState>(
builder: (context, state) {
if (state is YouLoadingState) {
return Center(child: CircularProgressIndicator());
}
if (state is DataLoaded) {
print(state.locations);
print(state.categories);
return Center(
child: Text('Categories and locations loaded!'),
);
}
},
),
);

我明白你的意思。

Example Case:
#some_bloc.dart (not in event or state file)
on<someEventNo1>((......) =>
emit(LoadingState());
emit(EmitResultAPI());
on<someEventNo2>((......) =>
emit(LoadingState());
emit(someState());
#main.dart
someMethod() {
BlocProvider.of<SomeBloc>(context).add(someEventNo1());
BlocProvider.of<SomeBloc>(context).add(someEventNo2());
}

如果你这样做你的代码,块生成器将不会捕获状态变化时,someEventNo1发出EmitResultAPI,因为你发送2个连续的BlocProvider.of<>()

解决方案:

BlocProvider.of<SomeBloc>(context).add(someEventNo1());
Future.delayed(Duration(miliseconds: 100)).then((valueFuture) => BlocProvider.of<SomeBloc>(context).add(someEventNo2()));

我会将逻辑放入块中。如果我理解正确的话,一旦数据被加载,就会触发一个事件。然后你可以在bool categoriesLoaded, locationsLoaded中创建2个变量,并在事件发生时设置为true。在mapEventToState中,你可以将这些事件映射器中的每一个转发到一个公共事件映射器,该事件映射器检查两个变量是否为真,然后发送适当的状态。inProgress状态可以显示哪些数据流已经加载。

最新更新