Flutter Bloc:登录状态切换后LoginScreen未自动销毁,需返回才显主页面
Flutter Bloc登录后页面未自动切换问题解答
问题背景
应用启动页状态判断逻辑
应用启动时通过BlocBuilder监听AuthenticationBloc状态,以此决定显示对应页面:
- 状态为
AuthenticationUnAuthenticated时,显示包含注册、登录子页面的AuthorizationScreen - 状态为
AuthenticationAuthenticated时,显示主页面NavigationController - 状态为
AuthenticationLoading时,显示加载页 - 未初始化状态下保留启动闪屏
对应实现代码:
Widget build(BuildContext context) { return BlocBuilder<AuthenticationBloc, AuthenticationState>( bloc: BlocProvider.of<AuthenticationBloc>(context), builder: (context, state) { // 只要状态是AuthenticationUnInitialized,就保留启动闪屏 if (state is! AuthenticationUninitialized) { FlutterNativeSplash.remove(); } if (state is AuthenticationUnAuthenticated) { return AuthorizationScreen(userRepository: userRepository); } if (state is AuthenticationAuthenticated) { return const NavigationController(); } if (state is AuthenticationLoading) { return const LoadingScreen(); } return const Center( child: Text('Auth State Error'), ); }, ); }
AuthorizationScreen跳转LoginScreen逻辑
AuthorizationScreen中通过自定义路由CustomPageRoute将LoginScreen推入导航栈:
PrimaryButton( onPressed: () { Navigator.of(context).push( CustomPageRoute( child: BlocProvider.value( value: _loginBloc, child: const SignInScreen(), ), ), ); }, child: const Text('Sign In'), )
问题描述
从AuthorizationScreen打开LoginScreen,输入信息完成登录后,AuthenticationBloc状态切换为AuthenticationAuthenticated,此时NavigationController已完成挂载,但LoginScreen仍为当前显示页面,仅当按下返回键将LoginScreen出栈后,NavigationController才会显示。
状态切换后,LoginScreen是否应自动被移除,直接显示NavigationController?
解答
状态切换后应该自动移除LoginScreen并直接显示NavigationController,当前问题源于页面层级结构的设计:
- 启动时
BlocBuilder返回的AuthorizationScreen是根页面; - 跳转
LoginScreen是通过Navigator.push将其推入根页面的导航栈,此时栈结构为:AuthorizationScreen→LoginScreen; - 登录成功后状态变更为
Authenticated,BlocBuilder会重新构建并返回NavigationController,但原有包含登录相关页面的导航栈并未被清空,新的主页面被覆盖在旧栈页面下方,因此无法自动显示。
解决方法
在状态变更为AuthenticationAuthenticated时,清空原有导航栈并替换为NavigationController,可通过两种方式实现:
- 在
BlocBuilder的状态判断分支中处理:
if (state is AuthenticationAuthenticated) { // 延迟执行导航操作,确保状态更新完成 WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const NavigationController()), (route) => false, // 清空所有页面 ); }); return const NavigationController(); }
- 在
LoginBloc处理登录成功事件的逻辑中,直接执行清空栈并跳转主页面的操作,确保登录完成后立即清理登录相关页面栈。
内容的提问来源于stack exchange,提问作者user14157206
相关产品推荐
相关产品推荐

