Flutter使用Navigator.push跳转后BlocConsumer<BlocC>找不到对应Provider报错
问题根本原因
Flutter 中通过
Navigator.push新增的路由页面默认挂载在MaterialApp节点下,你当前的BlocC仅在首页子树中通过BlocProvider提供,新打开的ChildC页面不在该BlocProvider的作用域范围内,因此无法检索到对应的BlocC实例。
解决方案
根据你的使用场景可以选择以下两种方案:
方案一:复用现有
BlocC实例(推荐当前场景使用)
如果你需要保留BlocC已经加载的状态,不需要重新请求数据,可以在跳转时通过BlocProvider.value将当前已创建的BlocC实例传递给新路由,修改跳转代码如下:TextButton( child: Text("Page C"), onPressed: () { Navigator.push( context, CupertinoPageRoute( builder: (newContext) => BlocProvider.value( // 从当前上下文获取已存在的BlocC实例 value: context.read<BlocC>(), child: ChildC(), ) ) ); } ),该方案不会重新执行
BlocC的初始化逻辑,已触发的FetchEvent和已有状态都会完整保留。方案二:提升BlocProvider层级
如果BlocC需要在应用内多个路由页面通用,可以将MultiBlocProvider的层级提升到MaterialApp的父节点,示例如下:void main() { runApp( MultiBlocProvider( providers: [ BlocProvider<BlocA>( create: (context) => BlocA()..add(FetchEvent()), ), BlocProvider<BlocC>( create: (context) => BlocC()..add(FetchEvent()), ), ], child: const MyApp(), // 你的根MaterialApp在此处返回 ) ); }这种方式下所有路由页面都属于
MultiBlocProvider的子树,无需额外传递即可在任意页面直接访问BlocA和BlocC实例,适合全局通用的业务Bloc场景。
注意事项
使用BlocProvider.value传递实例时,不要使用create参数创建新的Bloc实例,避免出现内存泄漏、状态不共享的问题。
内容的提问来源于stack exchange,提问作者Nithin Sai
相关产品推荐
相关产品推荐

