Flutter Firebase邮箱密码登录报错:Null check operator used on a null value
Flutter Firebase邮箱密码登录出现Null Check异常问题
错误信息
Exception has occurred. _CastError (Null check operator used on a null value)
问题描述
调用Firebase认证服务的signInWithEmailAndPassword方法时抛出上述异常,无法定位具体错误位置,已确认问题出在认证环节。
存在问题的函数
Future<User?> signInWithEmailPassword(String email, String password) async { await Firebase.initializeApp(); User? user; try { UserCredential userCredential = await _auth.signInWithEmailAndPassword( email: email, password: password, ); user = userCredential.user; if (user != null) { uid = user.uid; userEmail = user.email; SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setBool('auth', true); // prefs.setString('id', user.uid); } } on FirebaseAuthException catch (e) { if (e.code == 'user-not-found') { print('No user found for that email.'); } else if (e.code == 'wrong-password') { print('Wrong password provided.'); } } return user; }
完整认证模块代码
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/foundation.dart' show kIsWeb; final FirebaseAuth _auth = FirebaseAuth.instance; final GoogleSignIn googleSignIn = GoogleSignIn(); String? uid; String? name; String? userEmail; String? imageUrl; /// For checking if the user is already signed into the /// app using Google Sign In Future getUser() async { await Firebase.initializeApp(); SharedPreferences prefs = await SharedPreferences.getInstance(); bool? authSignedIn = prefs.getBool('auth'); print(authSignedIn); final User? user = _auth.currentUser; if (authSignedIn == true) { if (user != null) { uid = user.uid; name = user.displayName; userEmail = user.email; imageUrl = user.photoURL; prefs.setString('name', name!); prefs.setString('id', uid!); } } } /// For authenticating user using Google Sign In /// with Firebase Authentication API. /// /// Retrieves some general user related information /// from their Google account for ease of the login process Future<User?> signInWithGoogle() async { await Firebase.initializeApp(); User? user; if (kIsWeb) { GoogleAuthProvider authProvider = GoogleAuthProvider(); try { final UserCredential userCredential = await _auth.signInWithPopup(authProvider); user = userCredential.user; } catch (e) { print(e); } } else { final GoogleSignIn googleSignIn = GoogleSignIn(); final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn().catchError((onError) => print(onError));; if (googleSignInAccount != null) { final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication; final AuthCredential credential = GoogleAuthProvider.credential( accessToken: googleSignInAuthentication.accessToken, idToken: googleSignInAuthentication.idToken, ); try { final UserCredential userCredential = await _auth.signInWithCredential(credential); user = userCredential.user; } on FirebaseAuthException catch (e) { if (e.code == 'account-exists-with-different-credential') { print('The account already exists with a different credential.'); } else if (e.code == 'invalid-credential') { print('Error occurred while accessing credentials. Try again.'); } } catch (e) { print(e); } } } if (user != null) { uid = user.uid; name = user.displayName; userEmail = user.email; imageUrl = user.photoURL; SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setBool('auth', true); //prefs.setString('id', user.uid); //prefs.setString('name', user.displayName!); } return user; } Future resetPassword(String email) async { try { print(email); await FirebaseAuth.instance.sendPasswordResetEmail(email: email); } on FirebaseAuthException catch(e) { print(e); return false; } return true; } Future<User?> registerWithEmailPassword(String email, String password) async { await Firebase.initializeApp(); User? user; try { UserCredential userCredential = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); user = userCredential.user; if (user != null) { uid = user.uid; userEmail = user.email; //SharedPreferences prefs = await SharedPreferences.getInstance(); //prefs.setString('id', user.uid); //prefs.setString('name', user.displayName!); } } on FirebaseAuthException catch (e) { if (e.code == 'weak-password') { print('The password provided is too weak.'); } else if (e.code == 'email-already-in-use') { print('The account already exists for that email.'); } } catch (e) { print(e); } return user; } Future<User?> signInWithEmailPassword(String email, String password) async { await Firebase.initializeApp(); User? user; try { UserCredential userCredential = await _auth.signInWithEmailAndPassword( email: email, password: password, ); user = userCredential.user; if (user != null) { uid = user.uid; userEmail = user.email; SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setBool('auth', true); // prefs.setString('id', user.uid); } } on FirebaseAuthException catch (e) { if (e.code == 'user-not-found') { print('No user found for that email.'); } else if (e.code == 'wrong-password') { print('Wrong password provided.'); } } return user; } Future<String> signOut() async { await _auth.signOut(); SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setBool('auth', false); uid = null; userEmail = null; return 'User signed out'; } /// For signing out of their Google account void signOutGoogle() async { await googleSignIn.signOut(); await _auth.signOut(); SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setBool('auth', false); uid = null; name = null; userEmail = null; imageUrl = null; print("User signed out of Google account"); }
解决方案
1. 修正Firebase初始化逻辑
Firebase初始化只需在App启动时执行一次,重复调用会导致实例异常。修改main函数:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MyApp()); }
删除所有认证函数中的await Firebase.initializeApp();语句。
2. 捕获所有异常并定位错误行
当前代码仅捕获FirebaseAuthException,Null check错误属于未捕获的Error,扩展catch范围并打印堆栈:
try { UserCredential userCredential = await _auth.signInWithEmailAndPassword( email: email, password: password, ); // ... 后续代码 } on FirebaseAuthException catch (e) { // 原有错误处理 } catch (e) { print('异常详情: $e'); print(e.stackTrace); // 打印堆栈,精准定位错误行 }
3. 修复潜在的Null检查风险
getUser函数中name可能为null(邮箱注册用户无displayName),直接使用name!会触发异常,添加非空判断:
if (user != null) { uid = user.uid; name = user.displayName; userEmail = user.email; imageUrl = user.photoURL; if (name != null) { prefs.setString('name', name!); } prefs.setString('id', uid!); }
4. 验证_auth实例有效性
通过步骤1的初始化调整,确保全局_auth实例在Firebase初始化完成后才被调用,避免实例为null的情况。
内容的提问来源于stack exchange,提问作者Promaster
相关产品推荐
相关产品推荐

