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
相关产品推荐
相关产品推荐

