【问题标题】:how to retrieve specific data from Cloud Firestore using flutter and dart?如何使用颤振和飞镖从 Cloud Firestore 检索特定数据?
【发布时间】:2020-05-12 20:29:36
【问题描述】:

我一直在阅读 StackOverflow 阅读相关的帖子。但是,我还没有找到一个简单的解决方案,对于像我这样的初学者来说很容易理解。目前,我的 Cloud Firestore 数据库如下所示:

在用户输入足够的信息以填充文档中的每个字段后(ID 是通过电话身份验证的经过身份验证的用户的 UID),然后将其发送到数据库中。之后,用户被重定向到应该显示这些字段中的每一个的主屏幕。这就是我卡住的地方。下面是一个我已经开始实现的方法,它将返回一个字符串,该字符串将位于 Text 小部件中,以显示在数据库中找到的用户名。

String getUsername(FirebaseUser user, Firestore firestore) {

    //get the document reference
    DocumentReference docReference = firestore.document("Users/" + user.uid);

    Future<DocumentSnapshot> snapshot = docReference.get();

    Stream<DocumentSnapshot> stream = snapshot.asStream();

    //stub to ignore compiler warnings
    return null;
 }

如您所见,在使用 Futures 和 Streams 时,我相当迷茫。我在 youtube 上观看了 google flutter 开发人员的视频,他们帮助我达到了这一点。我还尝试使用 Future 对象提供的 then() 和 whenCompleted() 方法,但是我发现自己挖了一个越来越大的洞。

非常感谢所有帮助!

【问题讨论】:

标签: firebase flutter dart google-cloud-firestore


【解决方案1】:

要获取用户信息,请尝试以下操作:

Future<DocumentSnapshot> getUserInfo()async{
var firebaseUser = await FirebaseAuth.instance.currentUser();
return await Firestore.instance.collection("users").document(firebaseUser.uid).get();
}

然后在您的build() 方法中使用FutureBuilder

          FutureBuilder(
            future: getUserInfo(),
            builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                return ListView.builder(
                    shrinkWrap: true,
                    itemCount: 1,
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        title:
                            Text(snapshot.data.data["email"]),
                      );
                    });
              } else if (snapshot.connectionState == ConnectionState.none) {
                return Text("No data");
              }
              return CircularProgressIndicator();
            },
          ),

在方法中使用await 时,该方法需要声明为async。此外,您需要返回一个Future,以便能够在屏幕上显示结果,然后您需要使用FutureBuilder 小部件。

https://dart.dev/codelabs/async-await

【讨论】:

    【解决方案2】:

    当您只需要获取一次数据时,您可以使用 Futures,例如:

    final queryofdocs = await Firestore.instance.collection('Users').getDocuments()
    

    此代码返回一个Future&lt;QuerySnapshot&gt;,其中包含该集合中的所有文档。 然后你可以尝试像这样获取一个文档:

    final queryofonedocs = await Firestore.instance.document('users/uid').get()
    

    这会返回一个Future&lt;DocumentSnapshot&gt;,其中包含该文档中的所有字段。

    最后,您可以使用 Streams 监听数据变化。

    final suscription = await Firestore.instance.collection('tasks').snapshots()
    

    如果您更改某些数据并取消存储应用更新中的数据,这将返回 Stream&lt;QuerySnapshot&gt;

    DocumentSnapshots 在文档中有信息字段,QuerySnapshotDocumentSnapshots 的集合。

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      以下代码是null safe,并已更新为最新版本的库:

      var collection = FirebaseFirestore.instance.collection('users');
        
      FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
        future: collection.doc('${user.uid}').get(),
        builder: (_, snapshot) {
          if (snapshot.hasError) return Text('Error = ${snapshot.error}');
        
          if (snapshot.hasData) {
            var output = snapshot.data!.data();
            var value = output!['email']; // example@gmail.com
            return Text(value);
          }
        
          return Center(child: CircularProgressIndicator());
        },
      );
      

      【讨论】:

      • @Kamlesh 你需要使用我自己还没有尝试过的rxdart 包。
      • 谢谢亲爱的@CopsOnRoad,我已经用过它了,但可能有些东西不见了或还没用。
      • @Kamlesh 不幸的是,我对此无能为力。对不起:(
      【解决方案4】:

      这是我们如何做到这一点的过程

      创建 AuthController 类

      class AuthController extends GetxController {
      
        static AuthController to = Get.find();
      
        AppLocalizations_Labels labels;
        TextEditingController nameController = TextEditingController();
        TextEditingController emailController = TextEditingController();
        TextEditingController passwordController = TextEditingController();
      
        final FirebaseAuth _auth = FirebaseAuth.instance;
        final FirebaseFirestore _db = FirebaseFirestore.instance;
      
        Rx<User> firebaseUser = Rx<User>();
        Rx<UserModel> firestoreUser = Rx<UserModel>();
        final RxBool admin = false.obs;
      
        @override
        void onReady() async {
          //run every time auth state changes
          firebaseUser.value = await getUser;
          firebaseUser.bindStream(user);
          super.onReady();
        }
      
        @override
        void onClose() {
          nameController?.dispose();
          emailController?.dispose();
          passwordController?.dispose();
          super.onClose();
        }
      
      
        // Firebase user one-time fetch
        Future<User> get getUser async => _auth.currentUser;
      
        // Firebase user a realtime stream
        Stream<User> get user => _auth.authStateChanges();
      
        //Streams the firestore user from the firestore collection
        Stream<UserModel> streamFirestoreUser() {
          print('streamFirestoreUser()');
          if (firebaseUser?.value?.uid != null) {
            return _db
                .doc('/users/${firebaseUser.value.uid}')
                .snapshots()
                .map((snapshot) => UserModel.fromMap(snapshot.data()));
          }
      
          return null;
        }
      
        //get the firestore user from the firestore collection
        Future<UserModel> getFirestoreUser() {
          if (firebaseUser?.value?.uid != null) {
            return _db.doc('/users/${firebaseUser.value.uid}').get().then(
                (documentSnapshot) => UserModel.fromMap(documentSnapshot.data()));
          }
          return null;
        }
      
        //Method to handle user sign in using email and password
        signInWithEmailAndPassword(BuildContext context) async {
          final labels = AppLocalizations.of(context);
          showLoadingIndicator();
          try {
            await _auth.signInWithEmailAndPassword(
                email: emailController.text.trim(),
                password: passwordController.text.trim()
            );
            emailController.clear();
            passwordController.clear();
            hideLoadingIndicator();
          } catch (error) {
            hideLoadingIndicator();
            Get.snackbar(labels.auth.signInErrorTitle, labels.auth.signInError,
                snackPosition: SnackPosition.BOTTOM,
                duration: Duration(seconds: 7),
                backgroundColor: Get.theme.snackBarTheme.backgroundColor,
                colorText: Get.theme.snackBarTheme.actionTextColor);
          }
        }
      
      }
      

      创建 userInfo 类,通过 GetBuilder 显示用户数据

      class UserInfo extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          final labels = AppLocalizations.of(context);
      
          return GetBuilder<AuthController>(
            init: AuthController(),
            builder: (controller) => controller?.firestoreUser?.value?.uid == null
                ? Center(
                    child: CircularProgressIndicator(),
                  )
                : Scaffold(
                    appBar: AppBar(
                      title: Text(labels?.home?.title),
                      actions: [
                        IconButton(
                            icon: Icon(Icons.settings),
                            onPressed: () {
                              Get.to(SettingsUI());
                            }),
                      ],
                    ),
                    body: Center(
                      child: Column(
                        children: <Widget>[
                          SizedBox(height: 120),
                          Avatar(controller.firestoreUser.value),
                          Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              FormVerticalSpace(),
                              Text(
                                  labels.home.uidLabel +
                                      ': ' +
                                      controller.firestoreUser.value.uid,
                                  style: TextStyle(fontSize: 16)),
                              FormVerticalSpace(),
                              Text(
                                  labels.home.nameLabel +
                                      ': ' +
                                      controller.firestoreUser.value.name,
                                  style: TextStyle(fontSize: 16)),
                              FormVerticalSpace(),
                              Text(
                                  labels.home.emailLabel +
                                      ': ' +
                                      controller.firestoreUser.value.email,
                                  style: TextStyle(fontSize: 16)),
                              FormVerticalSpace(),
                              Text(
                                  labels.home.adminUserLabel +
                                      ': ' +
                                      controller.admin.value.toString(),
                                  style: TextStyle(fontSize: 16)),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-08-13
        • 1970-01-01
        • 2021-05-03
        • 2021-11-23
        • 2020-01-12
        • 1970-01-01
        • 2020-11-28
        • 1970-01-01
        相关资源
        最近更新 更多