基于Firebase的Flutter应用按用户角色跳转页面优化咨询
现有代码核心问题
- 强制解包风险:
FirebaseAuth.instance.currentUser!.uid使用了!强制非空断言,当用户未登录时会直接抛出空异常,是偶发崩溃的核心原因 - 异步逻辑顺序错误:
Database.getRole()是Future异步操作,你在.then回调中才拿到用户角色,但switch路由判断是同步执行的,等拿到角色数据时路由早就初始化完成,永远走默认配置 - Build方法滥用:build方法会被多次触发,你每次build都执行数据库查询操作,重复IO导致卡顿,且StatelessWidget无法响应异步数据变化更新页面
- 状态管理缺失:用户登录状态、角色信息没有统一持久化存储,每次启动/登录都要查库,拉长启动耗时
优化方案
1. 组件改造与异步处理
把MyApp改成StatefulWidget,初始化阶段统一处理登录状态和角色查询,启动阶段先展示加载页,等数据拿到之后再初始化路由:
class MyApp extends StatefulWidget { @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { bool isLoading = true; String? initialRoute; @override void initState() { super.initState(); _initRoute(); } Future<void> _initRoute() async { final user = FirebaseAuth.instance.currentUser; if (user == null) { initialRoute = "/"; } else { Database.setUserUid(user.uid); // 等待异步获取角色完成再判断路由 final userRole = await Database.getRole(); switch(userRole) { case "uprav": case "pred": initialRoute = "/repair-flow"; break; case "majs": initialRoute = "/majstor-flow"; break; default: initialRoute = "/"; } } setState(() => isLoading = false); } @override Widget build(BuildContext context) { if (isLoading) { // 加载阶段展示简单的启动屏,避免白屏 return MaterialApp( home: Scaffold(body: Center(child: CircularProgressIndicator())), ); } return ScreenUtilInit( designSize: Size(375, 812), builder: () => MaterialApp( debugShowCheckedModeBanner: false, title: 'Majstor', theme: ThemeData( primaryColor: Constants.primaryColor, scaffoldBackgroundColor: const Color.fromRGBO(255, 255, 255, 1), visualDensity: VisualDensity.adaptivePlatformDensity, textTheme: GoogleFonts.openSansTextTheme(), ), initialRoute: initialRoute, onGenerateRoute: _onGenerateRoute, ), ); } }
2. 角色信息持久化优化
不需要更换数据库,只要在首次查询到角色之后,把角色存在本地缓存(用shared_preferences即可),下次启动优先读缓存,后台再同步更新角色信息,大幅降低启动耗时:
- 登录成功时,查询完角色直接存本地缓存,同时跳转到对应页面
- 启动时先读本地缓存的角色直接初始化路由,后台异步拉取最新角色,如果和缓存不一致再触发路由跳转或者提示更新
3. 登录点击场景逻辑复用
登录按钮点击成功后,直接复用上面的角色判断逻辑,拿到角色后调用Navigator.pushReplacementNamed跳转到对应页面即可,不用写两套逻辑
注意事项
- 所有操作FirebaseAuth currentUser的地方都要做空判断,禁止用
!强制解包 - 不要在build方法里执行任何异步操作或者耗时逻辑
- 后续可以引入状态管理框架(Provider、Bloc等)统一管理用户登录态和角色信息,后续多处使用更方便
内容的提问来源于stack exchange,提问作者xxerav
相关产品推荐
相关产品推荐

