我怎样才能等到在 Flutter 中检索到 Firebase 数据库数据?

How can I wait until Firebase Database data is retrieved in Flutter?

我正在使用 flutter,我有一个简单的方法可以读取我数据库中存在的每个用户并将它们添加到列表中,一旦完成读取用户,该方法必须 return 包含所有数据的列表阅读,我的问题是我的函数不等待 Listener 完成阅读然后 returns 我的列表 (myList),甚至在 Listener 完成阅读之前。 我如何等待 return myList 直到 Listener 读取所有元素?

代码如下:

Future<List<String>> getUsers () async {

  List<String> myList = [];

  final mRef = FirebaseDatabase.instance.ref().child("Users");

  mRef.onValue.listen((event) async {
    for (final child in event.snapshot.children) {

      myList.add( child.value.toString() );  //ADDS THE VALUE TO THE LIST

    }
  });

  //RETURN THE LIST
  return myList;

}

我试图在我的 Listener 前面放置一个等待,但没有任何效果。

侦听器是等待更改(添加新文档等)并在发生更改时通知您的东西。所以它不是在你调用它之后 starts/ends 的东西 - 你通常在你的 Flutter class 的初始化中创建它,并且它会在任何事情发生变化时改变状态。

看起来你想抓住所有用户,一次,而不是像你目前正在做的那样listen

所以与其听,也许只是阅读数据。类似于:

// fetch all the documents
final allDocs =
        await FirebaseFirestore.instance.collection('users').get();
// map them to something like your strings.
final thedetails = allDocs.docs.map((DocumentSnapshot e) => e.data()!.toString()).toList();
return thedetails;

学习和理解 Firebase 如何与 Flutter 一起工作的一个非常好的方法是 FlutterFire, as you are dealing with future result you should use any state management to control at first if it is complete or not and then consider that return a promise and the way you manage that is different. This is an example for Future use as described in FlutterFire Cloud Firestore documentation:

class GetUserName extends StatelessWidget {
  final String documentId;

  GetUserName(this.documentId);

  @override
  Widget build(BuildContext context) {
    CollectionReference users = FirebaseFirestore.instance.collection('users');

    return FutureBuilder<DocumentSnapshot>(
      future: users.doc(documentId).get(),
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {

        if (snapshot.hasError) {
          return Text("Something went wrong");
        }

        if (snapshot.hasData && !snapshot.data!.exists) {
          return Text("Document does not exist");
        }

        if (snapshot.connectionState == ConnectionState.done) {
          Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
          return Text("Full Name: ${data['full_name']} ${data['last_name']}");
        }

        return Text("loading");
      },
    );
  }
}

但是如果您只需要以同步方式加载一次, 的答案是正确的。