如何使用Flutter和Dart从Cloud Firestore检索特定数据?

时间:2020-05-12 20:29:36

标签: firebase flutter dart google-cloud-firestore

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

My Cloud Firestore database layout

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

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;
 }

如您所见,在使用期货和流时,我相当失落。我已经看过Google flutter开发人员在youtube上录制的视频,他们帮助我掌握了这一点。我还尝试使用Future对象提供的then()和whenCompleted()方法,但是我发现自己在挖一个越来越大的洞。

非常感谢所有帮助!

4 个答案:

答案 0 :(得分:4)

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

std::is_same_v

然后在您的Future<DocumentSnapshot> getUserInfo()async{ var firebaseUser = await FirebaseAuth.instance.currentUser(); return await Firestore.instance.collection("users").document(firebaseUser.uid).get(); } 方法中使用FutureBuilder

build()

在方法内部使用 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小部件。

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

答案 1 :(得分:2)

以下代码是空安全,并已更新到最新版本的库:

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

答案 2 :(得分:1)

例如,仅需要一次获取数据时,可以使用期货:

program greek_letters

implicit none

write(*,*) "resistance is 100 Ω"

end program 

此代码返回该集合中所有文档的final queryofdocs = await Firestore.instance.collection('Users').getDocuments() 。 然后您可以尝试获取一个这样的文档:

Future<QuerySnapshot>

这将返回一个final queryofonedocs = await Firestore.instance.document('users/uid').get() ,其中包含该文档中的所有字段。

最后,您可以使用Streams收听数据更改。

Future<DocumentSnapshot>

如果您更改某些数据并在应用程序更新中将其存储后,将返回final suscription = await Firestore.instance.collection('tasks').snapshots()

Stream<QuerySnapshot>在文档上具有信息字段,而DocumentSnapshotsQuerySnapshot的集合。

希望有帮助

答案 3 :(得分:0)

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

创建 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)),
                      ],
                    ),
                  ],
                ),
              ),
            ),
    );
  }
}