Flutter邮箱密码注册时如何将UID与Email存入SharedPreferences
解决方案
1. 修复SignInProvider的变量赋值问题
原saveDataToSharedPreferences方法依赖类内的_email和_uid变量,但邮箱注册时没给这两个变量赋值,直接调用会触发空指针异常。给SignInProvider新增更新用户信息的方法:
class SignInProvider extends ChangeNotifier { // ... 原有代码不变 ... // 新增:更新Provider内的用户UID和Email Future updateUserInfo(String uid, String email) async { _uid = uid; _email = email; notifyListeners(); } // 可选优化:让saveData支持直接传参(避免依赖类内变量) Future saveDataToSharedPreferences({String? uid, String? email}) async { final SharedPreferences s = await SharedPreferences.getInstance(); await s.setString('email', email ?? _email!); await s.setString('uid', uid ?? _uid!); notifyListeners(); } }
2. 重构邮箱注册方法
原代码错误地在createUserWithEmailAndPassword后链式调用Provider方法,createUserWithEmailAndPassword返回的是UserCredential,不是SignInProvider实例,所以会报错。修改后的注册方法:
void signUp(String email, String password) async { if (_formkey.currentState!.validate()) { try { // 执行邮箱密码注册 UserCredential credential = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); if (credential.user != null) { final sp = context.read<SignInProvider>(); // 更新Provider内的用户信息 await sp.updateUserInfo( credential.user!.uid, credential.user!.email! ); // 保存到SharedPreferences并设置登录状态 await sp.saveDataToSharedPreferences(); await sp.setSignIn(); // 写入Firestore await postDetailsToFirestore(); } } catch (e) { Fluttertoast.showToast(msg: e.toString()); } } }
3. 优化postDetailsToFirestore(可选)
直接从SignInProvider获取用户信息,不用重复调用_auth.currentUser:
postDetailsToFirestore() async { FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance; final sp = context.read<SignInProvider>(); UserModel userModel = UserModel(); userModel.email = sp.email; userModel.uid = sp.uid; await firebaseFirestore .collection("users") .doc(sp.uid) .set(userModel.toMap()); Fluttertoast.showToast(msg: "Account created successfully "); Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => HomeScreen()), (route) => false, ); }
4. 确保自动登录正常触发
应用启动时,SignInProvider的构造函数已经调用checkSignInUser,在启动页判断登录状态即可自动跳转:
@override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { final sp = context.read<SignInProvider>(); if (sp.isSignedIn) { Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => HomeScreen()) ); } }); }
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

