如何在两个不同路由(页面)间正确配置BlocProvider?
问题分析
你遇到的ProviderNotFoundException核心原因是ScreenB的组件树不在ScreenABloc的BlocProvider作用域内:ScreenABloc是在导航到ScreenA时创建的,它的Provider仅包裹了ScreenAPage;当从ScreenA跳转到ScreenB时,ScreenB作为新页面被推入导航栈,其组件树与ScreenAPage是同级关系而非子级,因此ScreenB的context无法找到上层的ScreenABloc。
解决方案
不需要重新创建ScreenABloc(否则会丢失原有状态),只需在导航到ScreenB时,将已有的ScreenABloc实例通过BlocProvider.value传递给ScreenB即可:
1. 在ScreenA内部导航时传递Bloc实例
在ScreenAPage的导航逻辑中,使用处于ScreenABloc作用域内的context获取实例,并用BlocProvider.value包裹ScreenBPage:
// ScreenAPage内部的导航代码 Navigator.push( context, PageTransition( duration: const Duration(milliseconds: 400), child: BlocProvider.value( value: BlocProvider.of<ScreenABloc>(context), child: const ScreenBPage(), ), ), );
2. 在ScreenB中访问Bloc实例
此时在ScreenB的组件树中,可直接通过BlocProvider.of<ScreenABloc>(context)或BlocBuilder<ScreenABloc, ScreenAState>访问ScreenABloc的实例和状态,无需额外包裹BlocProvider.value(除非需要在ScreenB的深层子组件树中再次提供,但通常不需要)。
额外注意事项
- 确保获取ScreenABloc时使用的context是ScreenAPage内部的context(即处于ScreenABloc的Provider作用域内),不要使用路由配置中的外层context。
- 如果ScreenB是ScreenA的内嵌子组件(如弹窗、底部sheet)而非独立页面栈页面,直接在ScreenB中调用
BlocProvider.of<ScreenABloc>(context)即可,无需传递实例——因为此时ScreenB属于ScreenAPage的组件子树。
内容的提问来源于stack exchange,提问作者Daniel Roldán
相关产品推荐
相关产品推荐

