【发布时间】: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