Modal Bottom Sheet结合Bloc报错:上下文无对应Bloc导致BlocProvider.of()失败
解决BlocProvider.of()找不到Bloc的错误
你遇到的这个错误其实很常见——原因是showModalBottomSheet会生成一个全新的独立Widget树,弹窗里使用的context和你创建BlocProvider的父Widget树不在同一个作用域里,自然找不到对应的Bloc实例。下面给你几个实用的解决办法:
方案一:用BlocProvider.value传递已有的Bloc实例
在弹窗的builder里,通过BlocProvider.value把父树中的Bloc实例传递进去,让弹窗的Widget树也能访问到它:
void _showModal(BuildContext context) { // 先从父context获取Bloc实例 final theBloc = BlocProvider.of<TheBloc>(context); showModalBottomSheet<void>( context: context, builder: (_) { return BlocProvider.value( value: theBloc, child: MaterialButton( onPressed: () { // 新版本flutter_bloc推荐用read替代bloc方法 context.read<TheBloc>().add(TheEvent.someEvent()); }, child: const Text('Press button to add event to bloc') ), ); }, ); }
这里提一句:context.bloc<TheBloc>()在新版本的flutter_bloc里已经被弃用了,推荐用context.read<TheBloc>()来获取Bloc实例(适合在回调里使用),如果是在Widget构建时监听状态变化,就用context.watch<TheBloc>()。
方案二:提前获取Bloc实例再使用
如果你不想在弹窗里嵌套BlocProvider,可以在打开弹窗之前就拿到Bloc实例,之后直接调用它的方法:
void _showModal(BuildContext context) { // 提前获取Bloc实例 final theBloc = BlocProvider.of<TheBloc>(context); showModalBottomSheet<void>( context: context, builder: (_) { return MaterialButton( onPressed: () { // 直接调用已获取的Bloc实例 theBloc.add(TheEvent.someEvent()); }, child: const Text('Press button to add event to bloc') ); }, ); }
这种方法更直接,省去了弹窗里的BlocProvider嵌套,代码也更简洁。
方案三:把BlocProvider放在更高层级
如果这个Bloc需要在多个页面、弹窗中使用,建议把BlocProvider放在App的最顶层(比如MaterialApp外面),这样整个App的所有Widget树都能访问到这个Bloc实例:
void main() { runApp( BlocProvider( create: (context) => getIt<TheBloc>(), child: const MyApp(), ), ); }
这样不管是页面内还是弹窗里,都能轻松获取到Bloc,再也不会出现找不到的问题。
内容的提问来源于stack exchange,提问作者Gerry
相关产品推荐
相关产品推荐

