在显示主屏幕之前登录后从 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,这可以通过以某种方式监听您的提供商来完成。