从Firestore侦听回调返回列表 [英] Returning List from Firestore Listen callback
问题描述
我在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屋!