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

Flutter Google登录正常但Navigator.of(context)报空值无法跳转问题

问题排查与修复方案

根因定位

你遇到的跳转失败是因为异步操作完成后传入的BuildContext已经失效,导致Navigator.of(context)触发空检查异常,跳转逻辑直接崩溃没有执行,所以用户只能重启应用依靠Firebase的持久化登录态进入已登录页面。

现存问题点

  • Context有效性缺失校验:signInwithGoogle是异步方法,执行Google登录、Firebase认证、用户数据写入的耗时操作后,最初传入的context可能已经被销毁(比如用户登录过程中切后台、登录页被路由栈移除等场景),此时调用Navigator.of(context)会直接抛出你遇到的空值异常
  • 空安全判断顺序错误:先将FirebaseAuth.instance.currentUser赋值给非空类型User currentUser,再判断currentUser != null,如果登录完成后用户为空会直接触发空异常
  • 返回值不符合空安全规范:方法声明返回Future<String>,但最终返回null,会触发空安全编译/运行时警告

修复代码

class GoogleSignInProvider extends ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  User? user = FirebaseAuth.instance.currentUser;
  final GoogleSignIn _googleSignIn = GoogleSignIn();

  // 修改返回类型为可空,适配返回null的场景
  Future<String?> signInwithGoogle(BuildContext context) async {
    try {
      final GoogleSignInAccount? googleSignInAccount =
          await _googleSignIn.signIn();
      // 加判断避免用户取消登录后的空异常
      if (googleSignInAccount == null) return null;
      
      final GoogleSignInAuthentication googleSignInAuthentication =
          await googleSignInAccount.authentication;
      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleSignInAuthentication.accessToken,
        idToken: googleSignInAuthentication.idToken,
      );
      await _auth.signInWithCredential(credential);
    } on FirebaseAuthException catch (e) {
      print(e.message);
      rethrow;
    }

    // 先判断用户是否存在再操作
    final User? currentUser = _auth.currentUser;
    if (currentUser != null) {
      String uid = currentUser.uid;
      await usersRef.doc(uid).set({
        'id': uid,
        'email': currentUser.email,
        'username': currentUser.displayName,
        'photoUrl': currentUser.photoURL,
        'phone': '',
        'dob': '',
        'sex': ''
      });
      // 校验context是否仍挂载,再执行跳转
      if (context.mounted) {
        Navigator.of(context).pushReplacement(
            MaterialPageRoute(builder: (_) => TabScreen()));
      }
      user = currentUser;
      notifyListeners();
    }
    return null;
  }

  Future logout() async {
    await _googleSignIn.disconnect();
    await FirebaseAuth.instance.signOut();
    user = null;
    notifyListeners();
  }
}

额外优化建议

你也可以将跳转逻辑从Provider中移到UI层处理:调用signInwithGoogle方法后在UI层接收登录结果,由UI层自己控制跳转逻辑,能从根源避免context跨层使用导致的失效问题。

内容的提问来源于stack exchange,提问作者HaKim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:06:03