Flutter中showModalBottomSheet结合Bloc出现Provider查找失败问题
解决Flutter Bloc在showModalBottomSheet中找不到Provider的问题
错误原因
你遇到的问题有两个核心原因:
- 点击「应用」按钮时使用的
context是showModalBottomSheet的builder函数上下文,这个上下文位于你新建的BlocProvider<ProductsBloc>上层,无法访问到Bloc实例。 - 更关键的是,你当前在BottomSheet中新建了一个独立的
ProductsBloc实例,这会导致筛选操作无法同步更新原页面的产品数据——你应该和原页面共享同一个Bloc实例。
解决方案
方案一:共享原页面的Bloc实例(推荐)
通过BlocProvider.value将原页面的ProductsBloc实例传递给BottomSheet,确保筛选操作能作用于同一个Bloc:
// 调用showFilter的上下文必须在ProductsBloc的Provider范围内 showFilter(BuildContext context) => showModalBottomSheet( context: context, backgroundColor: Colors.white, isScrollControlled: true, builder: (context) { return BlocProvider.value( // 获取原页面的Bloc实例并传递 value: context.read<ProductsBloc>(), child: Container( padding: REdgeInsets.symmetric(horizontal: 8, vertical: 12), height: MediaQuery.of(context).size.height * 0.9, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 保留原有筛选组件代码 Row( children: [ Text( 'Фильтр', style: TextStyles.bodyStyle, ), const Spacer(), IconButton( onPressed: () { Navigator.pop(context); }, icon: const Icon(Icons.close)), ], ), SizedBox(height: 10.h), // ...其余筛选Dropdown组件... const Spacer(), ElevatedButton( onPressed: () { // 现在能正确访问到共享的Bloc实例 context.read<ProductsBloc>().add(LoadProductsWithFilter()); Navigator.pop(context); }, child: const Text('Применить')), ], ), ), ); });
注意:确保调用showFilter的上下文(即AppBar所在页面的context)已经被BlocProvider<ProductsBloc>包裹,比如原页面结构如下:
BlocProvider( create: (context) => ProductsBloc(), child: YourProductPage(), // 包含AppBar的页面 )
方案二:在BottomSheet内新建Bloc(不推荐)
如果确实需要在BottomSheet内使用独立的Bloc,需要通过Builder组件获取BlocProvider内部的上下文来读取实例:
showFilter(BuildContext context) => showModalBottomSheet( context: context, backgroundColor: Colors.white, isScrollControlled: true, builder: (context) { return BlocProvider<ProductsBloc>( create: (context) => ProductsBloc(), child: Container( padding: REdgeInsets.symmetric(horizontal: 8, vertical: 12), height: MediaQuery.of(context).size.height * 0.9, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 保留原有筛选组件代码 // ...其余筛选Dropdown组件... const Spacer(), // 用Builder获取BlocProvider内部的上下文 Builder( builder: (innerContext) { return ElevatedButton( onPressed: () { innerContext.read<ProductsBloc>().add(LoadProductsWithFilter()); Navigator.pop(context); }, child: const Text('Применить')); }, ), ], ), ), ); });
内容的提问来源于stack exchange,提问作者st4tic
相关产品推荐
相关产品推荐

