使用 blocbuilder 检查 bloc 状态
Posted
技术标签:
【中文标题】使用 blocbuilder 检查 bloc 状态【英文标题】:Checking bloc state with blocbuilder 【发布时间】:2021-03-19 11:27:22 【问题描述】:我正在从 API 获取项目列表并使用 BlocBuilder 构建它们。它可以工作并且构建了小部件列表,但是当我打印出来检查正在执行的状态部分时,我得到如下所示。为什么会出现“Nothing”?
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();
)
)
);
更新
添加了bloc代码以供参考。
集团
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');
【问题讨论】:
您也可以分享您的活动、州和集团吗?简短的回答:Nothing
出现是因为您错过了您从集团让步的一种可能状态。如果您使用另一个 if 语句捕获该状态,那么您将看不到任何内容。
查看更新。谢谢@Mahdi-Jafaree
您正在捕获所有状态,但未捕获 blocBuilder
中正在侦听新状态的 ProductLoading
状态。只需添加一个if( state is ProductLoading)
并处理它,然后Nothing
将不会被打印,因为您正在捕获所有状态。
【参考方案1】:
使用以下代码更新您的集团:
BLOC
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');
在您的代码中,您处于 yield ProductLoading
状态,但没有在 BlocBuilder 中处理该状态,这就是它绕过所有 if 语句并打印 Nothing 的原因。
所以另一种方法是在你的块构建中处理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();
)
)
);
【讨论】:
@stalwart1014 如果这不适合你,请告诉我 我认为没有必要在第一次提交ProductInitial()
,因为 bloc 自己会处理它。
@Mahdi-Jafaree 是的,这就是为什么我添加了两个选项来纠正这个问题。以上是关于使用 blocbuilder 检查 bloc 状态的主要内容,如果未能解决你的问题,请参考以下文章
Flutter bloc:更新状态不会重新调用 BlocBuilder
Flutter Bloc:更新后未调用 BlocBuilder,ListView 仍显示旧数据
flutter_bloc 的 BlocBuilder 能否避免重建 Widget 的未更改部分?