在显示主屏幕之前登录后从 firestore 获取数据
Fetch data from firestore after Sign In before showing HomeScreen
当用户第一次注册时,我希望他得到一个包含一些数据的自己的 firestore 文档。我想在主屏幕上显示此数据,但我收到一条错误消息,指出数据还不存在。热重载后数据就在那里,所以问题是在从 firestore 获取数据之前显示主屏幕,尽管我使用 FutureBuilder
。我只在用户第一次登录时遇到这个问题。
class GoogleSignInProvider extends ChangeNotifier {
final googleSignIn = GoogleSignIn();
GoogleSignInAccount _user;
GoogleSignInAccount get user => _user;
Future googleLogin() async {
try {
final googleUser = await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
await getUserData();
} catch (e) {
print(e.toString());
}
notifyListeners();
}
Future getUserData() async {
final myUser = FirebaseAuth.instance.currentUser;
bool userExist = await checkIfUserExists(myUser.uid);
if (userExist == false) {
print('User dont exist');
await FirebaseFirestore.instance.collection('users').doc(myUser.uid).set({
"email": myUser.email,
"plans": [],
"userScore": "100",
});
} else {
print('User exist');
}
/// Save userData from firestore in a Helper class which is shown on the homescreen
var userData = FirebaseFirestore.instance.collection('users').doc(myUser.uid);
return FutureBuilder(
future: userData.get(),
builder: (context, userDataSnapshot) {
if (userDataSnapshot.data == ConnectionState.done) {
var value = userDataSnapshot.data;
UserManager.userdata = value.data(); //static class where userData is stored
return null;
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
});
}
Future<bool> checkIfUserExists(String uid) async {
try {
var collectionRef = FirebaseFirestore.instance.collection('users');
var doc = await collectionRef.doc(uid).get();
return doc.exists;
} catch (e) {
throw e;
}
}
编辑
这是用户可以登录的按钮
ElevatedButton.icon(
onPressed: () {
final provider = Provider.of<GoogleSignInProvider>(context, listen: false);
provider.googleLogin();
},
icon: Icon(MdiIcons.google),
label: Text(
'Sign In with Google',
style: TextStyle(fontSize: 16),
),
),
这里的问题是 FutureBuilder 是一个小部件,它不应该用在等待未来完成的函数中,而是在另一个小部件中用于完成回调并根据它更改显示。
如果不渲染,FutureBuilder只会被实例化,占用内存。
您可能应该这样修改您的代码:
...
/// Save userData from firestore in a Helper class which is shown on the homescreen
var userData = await FirebaseFirestore.instance.collection('users').doc(myUser.uid).get();
UserManager.userdata = userData.data();
...
如果您想在主屏幕上添加 CircularProgress,这可以通过以某种方式监听您的提供商来完成。
当用户第一次注册时,我希望他得到一个包含一些数据的自己的 firestore 文档。我想在主屏幕上显示此数据,但我收到一条错误消息,指出数据还不存在。热重载后数据就在那里,所以问题是在从 firestore 获取数据之前显示主屏幕,尽管我使用 FutureBuilder
。我只在用户第一次登录时遇到这个问题。
class GoogleSignInProvider extends ChangeNotifier {
final googleSignIn = GoogleSignIn();
GoogleSignInAccount _user;
GoogleSignInAccount get user => _user;
Future googleLogin() async {
try {
final googleUser = await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
await getUserData();
} catch (e) {
print(e.toString());
}
notifyListeners();
}
Future getUserData() async {
final myUser = FirebaseAuth.instance.currentUser;
bool userExist = await checkIfUserExists(myUser.uid);
if (userExist == false) {
print('User dont exist');
await FirebaseFirestore.instance.collection('users').doc(myUser.uid).set({
"email": myUser.email,
"plans": [],
"userScore": "100",
});
} else {
print('User exist');
}
/// Save userData from firestore in a Helper class which is shown on the homescreen
var userData = FirebaseFirestore.instance.collection('users').doc(myUser.uid);
return FutureBuilder(
future: userData.get(),
builder: (context, userDataSnapshot) {
if (userDataSnapshot.data == ConnectionState.done) {
var value = userDataSnapshot.data;
UserManager.userdata = value.data(); //static class where userData is stored
return null;
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
});
}
Future<bool> checkIfUserExists(String uid) async {
try {
var collectionRef = FirebaseFirestore.instance.collection('users');
var doc = await collectionRef.doc(uid).get();
return doc.exists;
} catch (e) {
throw e;
}
}
编辑 这是用户可以登录的按钮
ElevatedButton.icon(
onPressed: () {
final provider = Provider.of<GoogleSignInProvider>(context, listen: false);
provider.googleLogin();
},
icon: Icon(MdiIcons.google),
label: Text(
'Sign In with Google',
style: TextStyle(fontSize: 16),
),
),
这里的问题是 FutureBuilder 是一个小部件,它不应该用在等待未来完成的函数中,而是在另一个小部件中用于完成回调并根据它更改显示。
如果不渲染,FutureBuilder只会被实例化,占用内存。
您可能应该这样修改您的代码:
...
/// Save userData from firestore in a Helper class which is shown on the homescreen
var userData = await FirebaseFirestore.instance.collection('users').doc(myUser.uid).get();
UserManager.userdata = userData.data();
...
如果您想在主屏幕上添加 CircularProgress,这可以通过以某种方式监听您的提供商来完成。