设置和检索用户配置文件颤振



dart/flutter新功能。我一直在遵循一些关于如何正确设置用户配置文件并使其在内存中可用的教程,而不是必须从firebase获取详细信息并将其放在一个地方。但是在尝试检索数据时,我遇到了一些后期初始化错误。

这是我的用户模型:


    class LakoUser  {
    
      //todo fill this with the necessary fields to create just 1 place to
      // retrieve the user's data that is global.... bad idea?
      // I tried extending this with User Class but got confused. I was wishing I can get some 
      // other fields of the User class for later use.
      final  String  uid;
  
      final String? username;
      final String? buyerMarker;
      final String? email;
      final String? mobileNum;
    
      LakoUser(
          {
            required this.uid,
            this.username,
            this.buyerMarker,
            this.email,
            this.mobileNum,
          });
    
      
       LakoUser.fromData(Map<String, dynamic> data)
        : uid = data['buyerId'],
          username = data['username'],
          buyerMarker = data['buyerMarker'],
          email = data['email'],
          mobileNum = data['mobileNum'];
    // storing to json format for quick saving to db
    Map<String, dynamic> toJson() {
      return {
        'buyerId': uid,
        'username': username,
        'buyerMarker': buyerMarker,
        'email': email,
        'mobileNum': mobileNum,
      };}
    factory LakoUser.fromJson(Map <String,dynamic> json)  {
       return LakoUser(
                 uid: json['buyerId'],
                 username: json['username'],
                 buyerMarker : json['buyerMarker'],
                 email: json['email'],
                 mobileNum: json['mobileNum']
       );}}

AuthService:

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  DatabaseService db = DatabaseService();
  late LakoUser _currentUser;
  LakoUser get currentUser  => _currentUser;
  
  //returns a AuthResult object that can ba a User or null once created/called thru registrations or signins
  LakoUser? _userfromSignIn(User? user) {
    return user != null ? LakoUser(uid: user.uid) : null;
  }
  //Fill _currentUser with data from the logged in user taken from db earlier
   populateCurrentUser(String? user) async {
    if (user != null) {
      //currentUser is a map object
      _currentUser = await db.getUser(user);
      print(_currentUser.mobileNum);
    }
  }
 
  Stream<LakoUser?> get user {
    // A sign-in or out is monitored and sent to 'user' parameter of _userfromSignIn
    return _auth.authStateChanges()
        .map((User? user) => _userfromSignIn(user));
  }
Future signInWithEmailAndPassword(String email, String password) async {
try {
  UserCredential resultOfSignIn = await _auth.signInWithEmailAndPassword(email: email, password: password);
  User? user = resultOfSignIn.user;
  await populateCurrentUser(user?.uid); //populate  this works. can confirm it fetches data
  return _userfromSignIn(user);
}catch(e) {
  print(e.toString());
  // return e;
  return null;
}

}

My Database Service:

Future  getUser(String uid) async {
//todo: fetch data from buyersCollection and save it a json
try {
  var document = await buyersCollection.doc(uid).get();
   Map <String, dynamic> userData = document.data() as Map <String, dynamic>;
  
  // var userData = await buyersCollection.doc(uid).get();
  return LakoUser.fromJson(userData);
} catch (e) {
  return e;
}

}

我正在尝试设置一个配置文件设置页面:

  class ProfileSettings extends StatefulWidget {
  const ProfileSettings({Key? key}) : super(key: key);
  @override
  _ProfileSettingsState createState() => _ProfileSettingsState();
}
class _ProfileSettingsState extends State<ProfileSettings> {
  String? username = "";
  String? email = "";
  final usernameCont = TextEditingController(text: "");
  final emailCont = TextEditingController(text: "");
  DatabaseService db = DatabaseService();

  final _profileSettingsKey = GlobalKey <FormState>();
  bool disableFocus = true;
  String? avatar = "";
  @override
  void initState() {
    super.initState();
    prefillFields();
  }
   ....  the Widget tree ...
Future <String?> prefillFields() async {
    //tried calling global auth and making an instance of AuthService here same error.    
    await auth.populateCurrentUser(auth.currentUser.uid);   <--- error begins here
    //how to retrieve the values so ican place them on the widgets below?
    // ignore the code below as i was trying to refactor it to get data from LakoUser instead of db
    username = db.username;
    usernameCont.value = (TextEditingValue(text: username.toString()));
    email = db.email;
    emailCont.value = (TextEditingValue(text: email.toString()));
    setState(() {
    });
    return null;
  }

似乎在登录后我丢失了currentUser中的数据:

    Unhandled Exception: LateInitializationError: Field '_currentUser@163456873' has not been initialized. E/flutter (31679): #0 AuthService._currentUser ...
E/flutter ( 6069): #0      AuthService.currentUser (package:mlako/services/auth.dart)

如何正确存储注册/登录后或刚启动时,当应用程序已经记住最后登录的用户?有很多问题。提前感谢!

所以你没有失去当前的用户,我假设你正在使用fillledstacks教程,因为他是显式地编写populateUser函数的人。

你的错误是非常清楚的,发生的事情是你没有初始化你的auth,因为你必须初始化一个实例的firebase之前,你可以得到uid。像这样,

  class ProfileSettings extends StatefulWidget {
  const ProfileSettings({Key? key}) : super(key: key);
  @override
  _ProfileSettingsState createState() => _ProfileSettingsState();
}
class _ProfileSettingsState extends State<ProfileSettings> {
  String? username = "";
  String? email = "";
  final usernameCont = TextEditingController(text: "");
  final emailCont = TextEditingController(text: "");
  DatabaseService db = DatabaseService();

  final _profileSettingsKey = GlobalKey <FormState>();
  bool disableFocus = true;
  String? avatar = "";
  @override
  void initState() {
    super.initState();
    prefillFields();
  }
   ....  the Widget tree ...
Future <String?> prefillFields() async {
final authInstance = FirebaseAuth.instance; 
    await auth.populateCurrentUser(authInstance.currentUser.uid);   

    username = db.username;
    usernameCont.value = (TextEditingValue(text: username.toString()));
    email = db.email;
    emailCont.value = (TextEditingValue(text: email.toString()));
    setState(() {
    });
    return null;
  }

还要确保您正在调用main函数中的服务定位器函数。

最新更新