我正在尝试使用Flutter的“ cloud_firestore”包找出如何对存储在Firestore集合中每个文档上的值求和。
我尝试了以下代码:
double queryValues() {
total = 0.0;
Firestore.instance
.collection('myCollection')
.snapshots()
.listen((snapshot) {
snapshot.documents.forEach((doc) => this.total +=
doc.data['amount']);
});
debugPrint(this.total.toString());
return total;
}
但是我最终将结果打印为0.0。如果删除第一行(总计= 0.0。),则总和有效,但如果重新加载,则值将增加一倍(总计为原来的总数)。
我知道他们说最好的解决方案是在每次写文档时都使用Cloud Function存储此汇总值,但是这很痛苦,因为我想在某些范围内使总计可供用户查询(月,年,周)。这些查询产生的文档数量很少,所以对我来说,仅迭代结果集合是理想的选择。
这是我发布的第一个问题,对此我深表感谢。
答案 0 :(得分:1)
如果您正在使用异步函数,则可以在listen()
方法内完成所有工作,或者在方法外等待,直到您确定内部所有操作都已完成。
处理第二种情况的“颤动”方法是使用setState()
。您build()
使用具有初始外部值的窗口小部件树,并且当异步函数完成时,您调用setState()
,以便使用新值重建窗口小部件树。
(请注意,在异步功能内,您可以使用在上一个操作上累积的fold()
列表方法。)
这是一个完整的简单应用,将使用外部总价值:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double total = 0.0;
@override
initState() {
super.initState();
queryValues();
}
void queryValues() {
Firestore.instance
.collection('myCollection')
.snapshots()
.listen((snapshot) {
double tempTotal = snapshot.documents.fold(0, (tot, doc) => tot + doc.data['amount']);
setState(() {total = tempTotal;});
debugPrint(total.toString());
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text("Total: $total")),
);
}
}
答案 1 :(得分:0)
正如Doug所说,数据是从Firestore异步加载的。到您打印总和时,尚未加载数据,forEach
还没有运行,并且总数仍为0.0
。
通过放置一些打印语句,最容易看到正在发生的事情:
print("Before calling listen");
Firestore.instance
.collection('myCollection')
.snapshots()
.documents((snapshot) {
print("Got data");
}
print("After calling listen");
运行此代码时,它会打印:
在调用监听之前
拨打电话后
获得数据
这可能不是您期望的顺序。但这解释了为什么没有结果和总和0.0
:数据尚未加载。
要解决此问题,您需要使用Dart的async
/ await
关键字。
double queryValues() async {
total = 0.0;
docs = await Firestore.instance
.collection('myCollection')
.snapshots()
.documents((snapshot);
docs.forEach((doc) => this.total += doc.data['amount']));
debugPrint(this.total.toString());
return total;
}
您会注意到,我也用listen()
替换了get()
,因为您只想获取一次文档(listen()
将保持活动状态,这意味着您无法返回结果)。
然后调用:
sum = await queryValues();
print(sum)
答案 2 :(得分:0)
CollectionReference _documentRef=Firestore.instance.collection("User");
_documentRef.getDocuments().then((ds){
if(ds!=null){
ds.documents.forEach((value){
print(value.data);
});
}
});