You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 00:18:02