从Firestore侦听回调返回列表 [英] Returning List from Firestore Listen callback

查看:48
本文介绍了从Firestore侦听回调返回列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在firebase中有一个函数,该函数旨在将所有文档收集到称为 history 的集合中,并将其添加到打算返回的列表中.

I have a function in firebase that is intended to get all documents in a collection called history and add it to a list intended to be returned.

问题是,我认为这是因为 .listen()是异步的,返回的列表始终为空.我知道可以正确查询数据,因为我可以在 forEach 函数中打印文档,但是将其添加到外部列表中是行不通的.

The problem is, and I think this is because .listen() is async, the list returned is always empty. I know the data is queried correctly because I can print the doc in the forEach function, but adding to a list outside doesn't work.

顺便说一句, myStream 是FireStore中历史记录集合的快照.

By the way, myStream is a snapshot of the history collection in FireStore.

我的职能需要成为未来吗?我该如何进行这项工作?

Does my function need to be a Future? How can I make this work?

这是我的代码:

List getHistory(String id) {
  List history;

  Firestore.instance.collection(id).snapshots().listen((data) {
    data.documents.forEach(
      (doc) => history.add(doc['day']),
    );
  });

  return history;
}

推荐答案

是的,您的函数将必须返回 Flutter的 FutureBuilder .

Yes, your function will have to return a Future.
As you correctly pointed out, the way Firestore data is retrieved is asynchronous. This means that whereever you want to use this data, you will have to await a Future.
If you want to do this in your UI, you can just make use of Flutter's FutureBuilder.

但是,首先,您需要重构 getHistory 函数.
您将无法使用 快照函数,如果您只想获取一次历史记录.如果您确实想使用实时更新,则只需将我说的所有内容翻译为 getDocuments FutureBuilder 示例的code>方法.

However, firstly you need to refactor your getHistory function.
You will not be able to use the snapshots function if you just want to get the history once. If you do want to use real-time updates, then you can just translate everything I say to a StreamBuilder, but then you cannot return your List, you could only yield it (I will just include an example implementation at the end).
Having said that, I am going to use the getDocuments method for the FutureBuilder example.

Future<List> getHistory(String id) async {
  List history;

  final List<DocumentSnapshot> documents = 
      (await Firestore.instance.collection(id).getDocuments()).documents;

  history = documents.map((documentSnapshot) => documentSnapshot['day']).toList();

  return history;
}

通知,我添加了 async 关键字,以便能够 await getDocuments 调用并包装返回值输入 Future .我使用了 List.map 方法 DocumentSnapshot 映射到您的 day 值(我也将您的 myStream 更改为Firestore调用,因为我不知道您的对象实际在您的班级中使用,因此您将不得不与访问Firestore集合的方式进行交换.
在下一步中,我将提供一个示例实现方式,该实现方式说明您如何使用 FutureBuilder 在您的UI中使用此功能:

Notice that I added the async keyword to be able to await the getDocuments call and wrapped the return type in a Future. I used the List.map method to map the DocumentSnapshot's to your day value (I also changed your myStream to a Firestore call because I cannot know the objects you actually use in your class, thus you will have to exchange that with how you access your Firestore collection).
In the next step, I will include an example implementation of how you would use this function in your UI using FutureBuilder:

FutureBuilder(
  future: getHistory(id),
  builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
    if (snapshot.hasError) return Text('${snapshot.error}');
    if (!snapshot.hasData) return CircularProgressIndicator();

    return ListView(
      children: snapshot.data
          .map((day) => ListTile(
                title: Text('$day'),
              ))
          .toList(),
    );
  },
);

我只是使用了 ListView 来演示如何在UI中使用数据列表.

I simply used a ListView to demonstrate how you could use your list of data in your UI.

因为我之前提到过,所以这里是使用 Stream 进行实时更新的示例实现(您必须将 FutureBuilder 交换StreamBuilder (如果您想在用户界面中使用它)

Because I mentioned it earlier, here would be an example implementation for having real-time updates using Stream (you would have to exchange your FutureBuilder with a StreamBuilder if you wanted to use it in your UI):

Stream<List> getHistory(String id) {
  final Stream<QuerySnapshot> documents = Firestore.instance.collection(id).snapshots();

  return documents.map((querySnapshot) {
    List history;
    final documents = querySnapshot.documents;

    history = documents.map((documentSnapshot) => documentSnapshot['day']);

    return history;
  });
}

在这种情况下,我只是映射 Stream ,它将对每个数据事件应用映射操作.我在上面提到了 yield ,但是这里没有必要使用它.您可以通过以下方式使用 yield ,这将更接近您的初始实现:

In this case, I am just mapping the Stream, which will apply the mapping operation for every data event. I mentioned yield above, but it is not necessary to use that here. You could use yield in the following manner, which would be closer to your initial implementation:

Stream<List> getHistory(String id) async* {
  await for (QuerySnapshot querySnapshot in Firestore.instance.collection(id).snapshots()) {
    List history;
    final documents = querySnapshot.documents;

    history = documents.map((documentSnapshot) => documentSnapshot['day']);

    yield history;
  }
}

这可能只是令人困惑,在这里完全没有必要,所以请忽略它:)

This is probably just confusing and it is completely unnecessary here, so just ignore it :)

这篇关于从Firestore侦听回调返回列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆