Flutter Bloc模式下启动页两种实现方案的选型咨询
Flutter启动页Bloc模式下两种页面切换方案对比分析
我是Flutter新手,正在开发启动页(Splash View),需要在该组件中检查已存储的认证信息,之后跳转至首页(NavigationHomeScreen)或登录页(SignInView),采用Bloc模式开发。目前纠结以下两种方案哪种更优:
方案1:使用MaterialPageRouter跳转页面
代码实现:
Widget build(BuildContext context) { return BlocBuilder<AuthBloc, AuthState>( builder: (context, state) { return BlocConsumer<AuthBloc, AuthState>( listener: (context, state) { if (state is SessionOK) { Navigator.push<dynamic>( context, MaterialPageRoute<dynamic>( builder: (BuildContext context) => scaffoldSafeAreaBuilder( child: const NavigationHomeScreen(), ), ), ); BuildContextProvider()((context) => context.loaderOverlay.hide()); } else if (state is SessionKO) { Navigator.push<dynamic>( context, MaterialPageRoute<dynamic>( // builder: (BuildContext context) => const LoginPage(), builder: (BuildContext context) => const SignInView(), ), ); BuildContextProvider()((context) => context.loaderOverlay.hide()); } }, builder: (BuildContext context, AuthState state) { return Scaffold( body: Center( child: Image.asset( "app_logo".toPng, height: context.dynamicHeight(0.2), width: context.dynamicWidth(0.9), ), ), ); }, ); }, ); }
方案1的优缺点
- 优势:符合Flutter原生导航逻辑,页面切换自带默认过渡动画,新页面生命周期正常触发;若用
pushReplacement可移除启动页导航栈,避免用户返回时回到启动页。 - 劣势:若误用
push而非pushReplacement,会导致启动页滞留在导航栈中,不符合启动页的使用场景。
方案2:通过变量赋值切换页面
代码实现:
class _SplashViewState extends State<SplashView> { late final AuthBloc authBloc; Widget page; @override void initState() { super.initState(); page = Scaffold( body: Center( child: Image.asset( "app_logo".toPng, height: context.dynamicHeight(0.2), width: context.dynamicWidth(0.9), ), ), ); print("splashview initState"); } @override Widget build(BuildContext context) { return BlocBuilder<AuthBloc, AuthState>( builder: (context, state) { return BlocConsumer<AuthBloc, AuthState>( listener: (context, state) { if (state is SessionOK) { setState(() { page = const NavigationHomeScreen(); }); BuildContextProvider()((context) => context.loaderOverlay.hide()); } else if (state is SessionKO) { setState(() { page = const SignInView(); }); BuildContextProvider()((context) => context.loaderOverlay.hide()); } }, builder: (BuildContext context, AuthState state) { return page; }, ); }, ); } }
方案2的优缺点
- 优势:无需处理导航栈,视觉上直接完成页面替换。
- 劣势:不符合Flutter导航规范,新页面生命周期受启动页影响;无默认过渡动画,需自行实现;用
setState维护页面变量属于冗余状态更新,和Bloc的状态管理逻辑冲突,增加复杂度。
更优方案推荐
优先选择方案1,并做以下优化:
- 用
Navigator.pushReplacement替代Navigator.push,移除启动页导航栈,避免用户返回问题; - 移除冗余的
BlocBuilder嵌套,直接使用BlocConsumer(它已包含BlocListener和BlocBuilder的功能); - 简化加载器隐藏逻辑,直接调用
context.loaderOverlay.hide()。
优化后的代码示例:
Widget build(BuildContext context) { return BlocConsumer<AuthBloc, AuthState>( listener: (context, state) { if (state is SessionOK) { Navigator.pushReplacement<dynamic, dynamic>( context, MaterialPageRoute<dynamic>( builder: (BuildContext context) => scaffoldSafeAreaBuilder( child: const NavigationHomeScreen(), ), ), ); context.loaderOverlay.hide(); } else if (state is SessionKO) { Navigator.pushReplacement<dynamic, dynamic>( context, MaterialPageRoute<dynamic>( builder: (BuildContext context) => const SignInView(), ), ); context.loaderOverlay.hide(); } }, builder: (BuildContext context, AuthState state) { return Scaffold( body: Center( child: Image.asset( "app_logo".toPng, height: context.dynamicHeight(0.2), width: context.dynamicWidth(0.9), ), ), ); }, ); }
内容的提问来源于stack exchange,提问作者loreeemartiii
相关产品推荐
相关产品推荐

