Flutter应用初始化Firebase后仍触发[core/no-app]错误求助
解决Firebase初始化完成前调用Auth导致的[core/no-app]错误
我一眼就看出问题出在哪了——你的Firebase初始化还没完成,代码就已经尝试访问Firebase Auth了!
问题根源
在initState中,你同时触发了initializeFlutterFire()和checkUserLogged():
initializeFlutterFire()是异步操作,需要时间完成Firebase App的初始化- 但
checkUserLogged()会立刻执行,这时候_initialized还是false,而且更关键的是,Firebase App根本还没创建出来,直接调用_auth.currentUser自然会抛出那个错误。就算之后_initialized变成true,你也没有再次触发checkUserLogged()来更新用户状态,所以loggedInUser始终是null,路由也不会正确跳转。
修复方案
我们需要确保Firebase初始化完成后再检查用户登录状态,同时可以利用Firebase Auth的状态流来更可靠地监听用户状态变化,下面是两种可行的修复方式:
方式1:初始化完成后立即检查用户状态
修改你的initializeFlutterFire()方法,在初始化成功后直接调用checkUserLogged(),并且移除initState中的checkUserLogged()调用:
void initializeFlutterFire() async { try { await Firebase.initializeApp(); // 初始化完成后再检查用户状态 checkUserLogged(); setState(() { _initialized = true; }); } catch (e) { setState(() { _error = true; }); } } @override void initState() { initializeFlutterFire(); // 移除这里的checkUserLogged()调用 super.initState(); }
同时,优化checkUserLogged()的逻辑,不需要再判断_initialized(因为现在只有初始化完成后才会调用它):
void checkUserLogged() { try { final user = _auth.currentUser; // currentUser现在可以同步获取,不需要await if (user != null) { setState(() { loggedInUser = user; }); } } catch (e) { print(e); } }
方式2:使用Auth状态流监听(更推荐)
这种方式不仅能解决初始化问题,还能实时监听用户登录/退出的状态变化,自动更新UI:
- 在
_myAppState中添加一个StreamSubscription来监听状态:
StreamSubscription<User> _authSubscription;
- 修改
initializeFlutterFire(),初始化完成后订阅状态流:
void initializeFlutterFire() async { try { await Firebase.initializeApp(); // 订阅用户状态变化流 _authSubscription = _auth.authStateChanges().listen((User user) { setState(() { loggedInUser = user; _initialized = true; }); }); } catch (e) { setState(() { _error = true; }); } }
- 在
dispose方法中取消订阅,避免内存泄漏:
@override void dispose() { _authSubscription?.cancel(); super.dispose(); }
- 移除原来的
checkUserLogged()方法和initState中的相关调用。
额外注意点
你的build方法中,StatusAlert.show不能直接放在MaterialApp之外(因为context需要在MaterialApp的子树中才能使用),建议添加加载中和错误状态的界面:
@override Widget build(BuildContext context) { if (_error) { return MaterialApp( home: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.close, color: Colors.red, size: 48), SizedBox(height: 16), Text('Something Went Wrong'), Text('We are sorry, try again later'), ], ), ), ), ); } if (!_initialized) { // 显示加载中界面,避免初始化完成前显示错误路由 return MaterialApp( home: Scaffold( body: Center(child: CircularProgressIndicator()), ), ); } return MaterialApp( initialRoute: loggedInUser == null ? WelcomeScreen.id : MainMenu.id, routes: { WelcomeScreen.id: (context) => WelcomeScreen(), RegistrationScreen.id: (context) => RegistrationScreen(), LogInScreen.id: (context) => LogInScreen(), MainMenu.id: (context) => MainMenu( loggedinUser: loggedInUser, ), }, ); }
这样修改后,你的应用就能正确等待Firebase初始化完成,再判断用户登录状态,不会再抛出那个错误了!
内容的提问来源于stack exchange,提问作者user13002252
相关产品推荐
相关产品推荐

