flutter_bloc调用BlocProvider.of()提示上下文中不存在SignupBloc如何解决
问题解决方法
核心报错原因
你遇到的Bloc找不到的报错,本质是SignupBloc的作用域没有覆盖到RegisterPage路由:
你当前main.dart的结构是MaterialApp的home参数为被MultiBlocProvider包裹的LoginPage,而通过Navigator跳转到的新路由默认是挂载在MaterialApp层级下的,不在MultiBlocProvider的子树范围内,所以RegisterPage的context找不到父级注册的SignupBloc。
除了这个核心问题外,你的代码还存在几处语法/逻辑错误,也需要同步修改才能正常运行:
SignUpSubmittedEvent构造要求5个参数,你调用时只传了手机号和密码2个参数,参数不匹配SignupBloc中调用makeRequestSignUp方法时参数缺失,且代码少了闭合括号,存在语法错误RegisterPage中直接调用了firstName、lastName、gender三个未定义的变量,运行会报错
具体修复步骤
1. 调整Bloc作用域覆盖RegisterPage
两种方案二选一即可:
方案A:全局暴露所有Bloc(推荐,适合多页面共用Bloc的场景)
把MultiBlocProvider提到MaterialApp的外层,让所有路由都能访问到已注册的Bloc,修改main.dart的代码:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { // 把MultiBlocProvider移到最外层 return MultiBlocProvider( providers: [ // 原有所有BlocProvider的代码原封不动复制到这里 BlocProvider<RecommendedBloc>( create: (BuildContext context) => RecommendedBloc( RecommendedForYouDataService(), ), ), BlocProvider<CuisineDishesBloc>( create: (BuildContext context) => CuisineDishesBloc( BrowseByCuisineDishesDataService(), ), ), BlocProvider<DetailsBloc>( create: (BuildContext context) => DetailsBloc( DetailsDataService(), ), ), BlocProvider<SearchBloc>( create: (BuildContext context) => SearchBloc( AllRestaurantDataService(), SearchRestaurantDataService()), ), BlocProvider<AllPhotosBloc>( create: (BuildContext context) => AllPhotosBloc(AllPhotosDataService()), ), BlocProvider<PlacePhotosBloc>( create: (BuildContext context) => PlacePhotosBloc(PlacePhotosDataService()), ), BlocProvider<FoodPhotosBloc>( create: (BuildContext context) => FoodPhotosBloc(FoodPhotosDataService()), ), BlocProvider<EventPhotosBloc>( create: (BuildContext context) => EventPhotosBloc(EventPhotosDataService()), ), BlocProvider<SignupBloc>( create: (BuildContext context) => SignupBloc(SignUpDataService()), ), ], // MaterialApp作为MultiBlocProvider的child child: MaterialApp( debugShowCheckedModeBanner: false, home: LoginPage(), ), ); } }
方案B:仅给RegisterPage单独传递Bloc
如果不想全局暴露SignupBloc,可以在LoginPage跳转RegisterPage的地方,用BlocProvider.value包裹路由,把当前的SignupBloc传递到新页面:
// LoginPage里跳转到RegisterPage的代码修改为 Navigator.push( context, MaterialPageRoute( builder: (context) => BlocProvider.value( value: BlocProvider.of<SignupBloc>(context), child: const RegisterPage(), ), ), );
2. 补全RegisterPage缺失的变量定义
在_RegisterPageState的变量定义部分,补上姓名和性别相关的控制器/变量:
// 原有变量基础上新增 final TextEditingController firstName = TextEditingController(); final TextEditingController lastName = TextEditingController(); String gender = "male"; // 可根据你的性别选择逻辑调整默认值
同时需要在Form的Widget列表里补上姓名输入、性别选择的对应控件,让用户可以输入相关信息。
3. 修正事件传参与语法错误
- 修正RegisterPage里提交事件的传参,补全所有要求的参数:
signupBloc = BlocProvider.of<SignupBloc>(context) ..add(SignUpSubmittedEvent(fName, lName, mNumber, pass, gen));
- 修正
Signup_bloc.dart里的参数缺失和语法错误:
try { SignUp? signup = await signUpDataService.makeRequestSignUp( event.firstName, event.lastName, event.phoneNumber, event.password, event.gender, ); // 补上缺失的参数和闭合括号 yield SignupSuccessState(signup!); } catch (e) { yield SignupErrorState(e.toString()); }
内容的提问来源于stack exchange,提问作者Mohammed Nabil
相关产品推荐
相关产品推荐

