#flutter #dart #bloc
#трепетание #дротик #блок
Вопрос:
Я извлекаю список элементов из API и создаю их с помощью blockbuilder. Это работает, и список виджетов создается, но когда я распечатываю, чтобы проверить, какая часть состояния выполняется, я получаю, как показано ниже. Почему появилось «Ничего»?
ProductInitial
fetching product //from bloc when fetching api
Nothing
fetching complete //from bloc after fetching api
ProductSuccess
Главная
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<ProductBloc>(
create: (BuildContext context) => ProductBloc()..add(FetchProduct())
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: MainScreen(),
)
);
}
}
Экран списка
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.all(10.0),
child: BlocBuilder<ProductBloc, ProductState>(
builder: (context, state) {
if(state is ProductInitial){
print('ProductInitial');
return buildLoadingWidget();
}
if(state is ProductSuccess){
print('ProductSuccess');
return _buildProductListWidget(state.products);
}
if(state is ProductFailed){
print('ProductFailed');
return Center(
child: Text('Something went wrong'),
);
}
print('Nothing');
return buildLoadingWidget();
}
)
)
);
}
Обновить
Добавлен код блока для справки.
Блок
class ProductBloc extends Bloc<ProductEvent, ProductState> {
ProductBloc() : super(ProductInitial());
ProductRepository _repository = ProductRepository();
@override
Stream<ProductState> mapEventToState(ProductEvent event,) async* {
if(event is FetchProduct){
yield ProductLoading();
try{
print('fetching product');
final List<ProductModel> products = await _repository.getProducts();
yield ProductSuccess(products);
print('fetching complete');
}catch(e){
yield ProductFailed();
print(e);
print('fetching failed');
}
}
}
}
Комментарии:
1. можете ли вы также поделиться своими событиями, состояниями и блоками? для краткости:
Nothing
появляется потому, что вы пропустили одно возможное состояние, которое вы получаете от блока. если вы поймаете это состояние с помощью другого оператора if, то вы ничего не увидите.2. смотрите обновление. спасибо @Mahdi-Jafaree
3. вы улавливаете все состояния, но не улавливаете
ProductLoading
состояние внутри вашегоblocBuilder
, которое прослушивает новые состояния. просто добавьтеif( state is ProductLoading)
и обработайте его, послеNothing
чего он не будет напечатан, так как вы улавливаете все состояния.
Ответ №1:
Обновите свой блок с помощью приведенного ниже кода:
БЛОК
class ProductBloc extends Bloc<ProductEvent, ProductState> {
ProductBloc() : super(ProductInitial());
ProductRepository _repository = ProductRepository();
@override
Stream<ProductState> mapEventToState(ProductEvent event,) async* {
if(event is FetchProduct){
yield ProductInitial();
try{
print('fetching product');
final List<ProductModel> products = await _repository.getProducts();
yield ProductSuccess(products);
print('fetching complete');
}catch(e){
yield ProductFailed();
print(e);
print('fetching failed');
}
}
}
}
Как и в вашем коде, вы находитесь ProductLoading
в состоянии yield, но не обрабатывали это состояние в своем blockbuilder, поэтому он обходит все операторы if и ничего не печатает.
Итак, другой способ — это обработка ProductLoading
в вашей сборке блоков, как показано ниже
Экран списка
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.all(10.0),
child: BlocBuilder<ProductBloc, ProductState>(
builder: (context, state) {
if(state is ProductInitial){
print('ProductInitial');
return buildLoadingWidget();
}
if(state is ProductLoading){
print('ProductLoading');
return buildLoadingWidget();
}
if(state is ProductSuccess){
print('ProductSuccess');
return _buildProductListWidget(state.products);
}
if(state is ProductFailed){
print('ProductFailed');
return Center(
child: Text('Something went wrong'),
);
}
print('Nothing');
return buildLoadingWidget();
}
)
)
);
}
Комментарии:
1. @stalwart1014 дайте мне знать, если это не сработает для вас
2. Я думаю, что нет необходимости уступать
ProductInitial()
в первый раз, поскольку блок сам справится с этим.3. @Mahdi-Jafaree да, верно, вот почему я добавил два варианта, чтобы исправить эту проблему.