Firebase 如何在Flatter firestore中编辑用户

Firebase 如何在Flatter firestore中编辑用户,firebase,flutter,dart,google-cloud-firestore,Firebase,Flutter,Dart,Google Cloud Firestore,我一直在学习Flatter如何使用firestore,现在我正在使用用户身份验证和密码、电子邮件和用户名,当创建用户时,电子邮件和密码使用uid保存,但用户名和电子邮件(再次)使用不同的uid保存在firestore中,顺便说一句,我已经尝试了很多方法使它具有相同的id,但我目前找不到方法。除此之外,还有一个功能可以编辑用户名并保存这些更改。当尝试实现编辑功能时会出现问题,因为编辑表单除了加载屏幕外,不会返回任何输出,我认为发生此错误是因为UID。我如何解决这个问题 models/user.da

我一直在学习Flatter如何使用firestore,现在我正在使用用户身份验证和密码、电子邮件和用户名,当创建用户时,电子邮件和密码使用uid保存,但用户名和电子邮件(再次)使用不同的uid保存在firestore中,顺便说一句,我已经尝试了很多方法使它具有相同的id,但我目前找不到方法。除此之外,还有一个功能可以编辑用户名并保存这些更改。当尝试实现编辑功能时会出现问题,因为编辑表单除了加载屏幕外,不会返回任何输出,我认为发生此错误是因为UID。我如何解决这个问题

models/user.dart

class CustomUser {
  final String uid;

  CustomUser({this.uid});
}

class UserData {
  final String uid;
  final String name;

  UserData({this.uid, this.name});
}
models/username.dart

class Username {
  final String name;

  Username({this.name});
}
服务/auth.dart

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;


  // create user obj based on fb user
  CustomUser _userFromFirebaseUser(User user) {
    return user != null ? CustomUser(uid: user.uid) : null;
  }

  Stream<CustomUser> get user {
    return _auth.authStateChanges().map(_userFromFirebaseUser);
  }

  //signin email password
  Future signInWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.signInWithEmailAndPassword(
          email: email, password: password);
      User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  //signup
  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(
          email: email, password: password);
      User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  //signout
  Future signOut() async {
    try {
      return await _auth.signOut();
    } catch (e) {
      print(e.toString());
      return null;
    }
  }
类身份验证服务{
final FirebaseAuth _auth=FirebaseAuth.instance;
//基于fb用户创建用户obj
CustomUser\u userFromFirebaseUser(用户){
返回用户!=null?CustomUser(uid:user.uid):null;
}
流获取用户{
返回_auth.authStateChanges().map(_userFromFirebaseUser);
}
//登录电子邮件密码
带email和密码(字符串电子邮件、字符串密码)的未来登录异步{
试一试{
UserCredential result=wait_auth.signin with Email and Password(
电子邮件:电子邮件,密码:密码);
User=result.User;
返回_userFromFirebaseUser(用户);
}捕获(e){
打印(如toString());
返回null;
}
}
//报名
未来的注册表,带emailandpassword(字符串电子邮件、字符串密码)异步{
试一试{
UserCredential结果=等待_auth.createUserWithEmailAndPassword(
电子邮件:电子邮件,密码:密码);
User=result.User;
返回_userFromFirebaseUser(用户);
}捕获(e){
打印(如toString());
返回null;
}
}
//签到
Future signOut()异步{
试一试{
return wait_auth.signOut();
}捕获(e){
打印(如toString());
返回null;
}
}
服务/database.dart

class DatabaseService {
  final String uid;
  DatabaseService({this.uid});

  final CollectionReference userCollection = FirebaseFirestore.instance.collection('usernames');

  Future updateUserData(String name) async {  // this is the function that has to edit the username
    return await userCollection.doc(uid).set({
      'name': name,
    });
  }

  Future uploadUserInfo(userMap) async {  // this function adds username and email to firestore
    return await userCollection.doc(uid).set(userMap);
  }

  List<Username> _usernameListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return Username(
        name: doc.data()['name'] ?? '',
      );
    }).toList();
  }

  // userData from snapshot
  UserData _userDataFromSnapshot(DocumentSnapshot snapshot) {
    return UserData(
      uid: uid,
      name: snapshot.data()['name'],
    );
  }

  Stream<List<Username>> get usernames {
    return userCollection.snapshots().map(_usernameListFromSnapshot);
  }

  Stream<UserData> get userData {
    return userCollection.doc(uid).snapshots().map(_userDataFromSnapshot);
  }
}
类数据库服务{
最后一个字符串uid;
数据库服务({this.uid});
final CollectionReference userCollection=FirebaseFirestore.instance.collection(“用户名”);
Future updateUserData(字符串名称)async{//这是必须编辑用户名的函数
return wait userCollection.doc(uid).set({
“名称”:名称,
});
}
Future uploadUserInfo(userMap)async{//此函数将用户名和电子邮件添加到firestore
返回wait userCollection.doc(uid.set)(userMap);
}
列表_usernameListFromSnapshot(QuerySnapshot快照){
返回snapshot.docs.map((doc){
返回用户名(
名称:doc.data(),
);
}).toList();
}
//来自快照的用户数据
UserData\u userDataFromSnapshot(DocumentSnapshot快照){
返回用户数据(
uid:uid,
名称:snapshot.data()['name'],
);
}
流获取用户名{
返回userCollection.snapshots().map(_usernamelistfromsapshot);
}
流获取用户数据{
返回userCollection.doc(uid).snapshots().map(\u userdatafromsapshot);
}
}
register.dart(用用户名注册用户的代码)

onPressed:()异步{
if(_formKey.currentState.validate()){
设置状态(()=>加载=真);
动态结果=等待_auth.registerWithEmailAndPassword(电子邮件,密码)。然后((val){
映射用户信息映射={
“姓名”:姓名,
“电子邮件”:电子邮件,
};
uploadUserInfo(userInfoMap);
});
如果(结果==null){
设置状态(){
错误='请提供有效的电子邮件';
加载=假;
});
}
}
}),
编辑格式.省道

final _formKey = GlobalKey<FormState>();
String _currentName;

final user = Provider.of<CustomUser>(context);

StreamBuilder<UserData>(
      stream: DatabaseService(uid: user.uid).userData,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          UserData userData = snapshot.data;
          return Form(
              key: _formKey,
              child: Column(
                children: <Widget>[
                  Text('edit username!'),
                  SizedBox(
                    height: 30,
                  ),
                  TextFormField(
                    // initialValue: userData.user gives a initial text to the input
                    validator: (val) => val.isEmpty ? 'Please enter a name' : null,
                    onChanged: (val) => setState(() => _currentName = val),
                  ),
                  RaisedButton(
                      child: Text('Save'),
                      onPressed: () async {
                        if (_formKey.currentState.validate()) {
                          print('update if good');
                          await DatabaseService(uid: user.uid).updateUserData(
                            _currentName ?? userData.name,
                          );
                        }
                        Navigator.pop(context);
                      })
                ],
              ));
        } else {
          return Loading();
        }
      },
    );
final_formKey=GlobalKey();
字符串_currentName;
最终用户=提供者(上下文);
StreamBuilder(
流:DatabaseService(uid:user.uid).userData,
生成器:(上下文,快照){
if(snapshot.hasData){
UserData UserData=snapshot.data;
报税表(
键:_formKey,
子:列(
儿童:[
Text('编辑用户名!'),
大小盒子(
身高:30,
),
TextFormField(
//initialValue:userData.user为输入提供初始文本
验证程序:(val)=>val.isEmpty?“请输入名称”:null,
一旦更改:(val)=>setState(()=>\u currentName=val),
),
升起的按钮(
子项:文本('Save'),
onPressed:()异步{
if(_formKey.currentState.validate()){
打印(‘良好时更新’);
等待数据库服务(uid:user.uid)(
_currentName??userData.name,
);
}
Navigator.pop(上下文);
})
],
));
}否则{
返回加载();
}
},
);

如果您有任何问题,请告诉我;)

在您的
注册表中。dart
registerWithEmailAndPassword
方法返回一个
用户
对象,该对象包含FirebaseAuth内部创建的
uid
,但是,您似乎没有使用此
uid
来更新
Firestore用户文档。我已经实现了下面应该做的一个示例

dynamic result=wait_auth.register with email and password(email,password)。然后((val){
映射用户信息映射={
“姓名”:姓名,
“电子邮件”:电子邮件,
};
数据库服务(uid:val.uid).uploadUserInfo(userInfoMap);
});
我刚刚意识到,您的
注册表WithEmailandPassword
函数返回的是
CustomUser
,而不是Firebase
Use
final _formKey = GlobalKey<FormState>();
String _currentName;

final user = Provider.of<CustomUser>(context);

StreamBuilder<UserData>(
      stream: DatabaseService(uid: user.uid).userData,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          UserData userData = snapshot.data;
          return Form(
              key: _formKey,
              child: Column(
                children: <Widget>[
                  Text('edit username!'),
                  SizedBox(
                    height: 30,
                  ),
                  TextFormField(
                    // initialValue: userData.user gives a initial text to the input
                    validator: (val) => val.isEmpty ? 'Please enter a name' : null,
                    onChanged: (val) => setState(() => _currentName = val),
                  ),
                  RaisedButton(
                      child: Text('Save'),
                      onPressed: () async {
                        if (_formKey.currentState.validate()) {
                          print('update if good');
                          await DatabaseService(uid: user.uid).updateUserData(
                            _currentName ?? userData.name,
                          );
                        }
                        Navigator.pop(context);
                      })
                ],
              ));
        } else {
          return Loading();
        }
      },
    );