【问题标题】:How to edit a user in flutter firestore如何在flutter firestore中编辑用户
【发布时间】:2020-12-12 15:49:31
【问题描述】:

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

models/user.dart

class CustomUser {
  final String uid;

  CustomUser({this.uid});
}

class UserData {
  final String uid;
  final String name;

  UserData({this.uid, this.name});
}

模型/用户名.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;
    }
  }

services/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);
  }
}

register.dart(使用用户名注册用户的代码)

onPressed: () async {
  if (_formKey.currentState.validate()) {
    setState(() => loading = true);
    dynamic result = await _auth.registerWithEmailAndPassword(email, password).then((val) {
      Map<String, String> userInfoMap = {
        "name": name,
        "email": email,
      };
      databaseService.uploadUserInfo(userInfoMap);
    });
    if (result == null) {
      setState(() {
        error = 'please suply a valid email';
          loading = false;
      });
    }
  }
}),

editForm.dart

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();
        }
      },
    );

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

【问题讨论】:

  • 在您的 register.dart 中添加您初始化 databaseService 的代码?用户实际 uid 和 firestore id 不同的原因源于此
  • 您可以使用自己的 uid 将用户存储在 firestore 中。只需在注册时检索 uid,然后在之后执行类似 Firestore.instance.collection('users').document(authResult.user.uid).setData({ 'username': username, 'email': email}) 的操作您可以使用与用户 uid 相同的文档 ID 添加到用户集合中。
  • @ByteMe 那是我不太明白的,我已经尝试过了,但我认为我做错了,你能解释一下如何做到这一点吗?
  • uid 应该从 firebase register 函数中恢复,但您似乎没有这样做。我会在大约 6 小时内尝试回答问题
  • @ByteMe 好的,谢谢

标签: firebase flutter dart google-cloud-firestore


【解决方案1】:

在您的 register.dart 中,registerWithEmailAndPassword 方法返回一个 User 对象,其中包含由 FirebaseAuth 内部创建的 uid 但是,您似乎没有使用此 uid 来更新您的 @987654326 @用户文档。我已经实现了一个应该在下面完成的示例。

dynamic result = await _auth.registerWithEmailAndPassword(email, password).then((val) {
  Map<String, String> userInfoMap = {
    "name": name,
    "email": email,
  };
  
  DatabaseService(uid: val.uid).uploadUserInfo(userInfoMap);
});

我刚刚意识到您的 registerWithEmailAndPassword 函数返回 CustomUser 而不是 Firebase User。我只是对其进行了修改以使其正常工作。

//signup
  Future<User> registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(
          email: email, password: password);
      return result.user;
    } catch (e) {
      print(e.toString());
      return null;
    }
  }
//editFrom.dart
//form validation function
Map<String, String> userMap = {'name': currentName}; 
await DatabaseService(uid: user.uid).uploadUserInfo(userMap);

旁注:使用Futures 时,如果您指定预期的返回类型会有所帮助,因为这将有助于您进行调试。上面的功能我已经完成了

【讨论】:

  • 此代码确实为用户名、电子邮件和密码保存了相同的 uid,但不编辑用户名
  • hmm,在你的editForm.dart中,在你调用updateUserData函数之前,你能不能打印出user.uid的值来确保它不为空
  • 它是空的,我已经通过添加地图Map&lt;String, String&gt; userMap {'name': =currentName}; await DatabaseService(uid: user.uid).uploadUserInfo( userMap,); 解决了这个问题,您可以将其添加到您的答案中以便其他人可以看到吗?
  • 现在代码编辑用户名并将其保存在firestore中
猜你喜欢
  • 2019-07-11
  • 1970-01-01
  • 2021-01-25
  • 2021-09-05
  • 2019-06-12
  • 1970-01-01
  • 2019-10-22
  • 2021-12-29
  • 2021-02-10
相关资源
最近更新 更多