我正在尝试开发一个Flutter Android应用程序,该应用程序将与Cloud Firestore数据库进行通信。我希望它遍历一系列引用中的每个文档,从每个文档中获取一个值,从读取的值中增加一个计数器,然后将其作为文本小部件返回。问题是,尽管我可以从云中读取的值正确打印出计数器,但是读取的值似乎没有反映在UI中。
我尝试使用StreamBuilder和FutureBuilder。我的最后一次尝试是使函数返回Future,并等待读取值,但无济于事。用户界面上反映的就是“未来的实例”。
array (
0 =>
array (
'id' => 'C:\\xampp\\htdocs\\restore_point_backups_fagardesignscom\\files',
'name' => 'sitebackup_2019_07_19_08_52_37.zip',
'created' => 1563519157,
),
4 =>
array (
'id' => 'C:\\xampp\\htdocs\\restore_point_backups_fagardesignscom\\files',
'name' => 'sitebackup_2019_07_21_10_12_29.zip',
'created' => 1563696754,
),
5 =>
array (
'id' => 'C:\\xampp\\htdocs\\restore_point_backups_fagardesignscom\\files',
'name' => 'sitebackup_2019_Jul_21_10_17_58.zip',
'created' => 1563697083,
),
)
“ print(wrapper.value)”调用将打印期望值,但不会在UI中显示。
答案 0 :(得分:0)
您必须使用仅当ListTile
方法完成时才会呈现calculatePrice
的FutureBuilder。
在下面的示例中,ListTile
在计算进行中包含一个临时的“ ...”,在计算完成时包含一个实际的结果。
Future<double> calculatePrice(DocumentSnapshot pedido) async {
priceWrapper wrapper = priceWrapper(0);
for (DocumentReference d in pedido.data['requested_products']) {
var f = await d.get();
wrapper.value += f['value'];
}
return wrapper.value;
}
Widget buildListItem(BuildContext context, DocumentSnapshot document) {
Future<double> getPrice = calculatePrice(document);
return FutureBuilder(
future: getPrice,
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListTile(
//...
trailing: Text("${snapshot.data}",
style: Theme.of(context).textTheme.subtitle,
);
}
else {
return ListTile(
//...
trailing: Text("...",
style: Theme.of(context).textTheme.subtitle,
);
}
}
);
}
现在,关于为什么您的代码似乎可以工作但无法正常工作的问题,所有内容都位于这段代码中
for (DocumentReference d in pedido.data['requested_products']) {
d.get().then( (f) {
wrapper.value += f['value'];
print(wrapper.value);
});
}
print(wrapper.value);
get
方法是一种异步方法,不会中断执行流程。 Insteand将在then
完成后注册一个回调(在get
中)。由于执行流程没有中断,因此for
循环将对所有数据进行迭代。然后,将执行最后一个print
语句。
稍后,将调用回调。
由于代码不会被中断,因此您的calculatePrice
方法将非常有效地完成拼写,但是结果为priceWrapper(0)
(wrapper
的初始值)。那就是将用来创建您的ListTile
的值,以及为什么它似乎不起作用的原因。
使用FutureBuilder
可以在完成所有异步工作后管理应用程序的呈现。
答案 1 :(得分:-1)
在您的calculatePrice函数中等待。
for (DocumentReference d in pedido.data['requested_products']) {
await d.get().then( (f) {
wrapper.value += f['value'];
print(wrapper.value);
});
}
返回的是Future,而不是double
Widget buildListItem(BuildContext context, DocumentSnapshot document) {
calculatePrice(document).get().then( (price) {
return ListTile(
trailing: Text("$price"),
style: Theme.of(context).textTheme.subtitle,
)
}
).catchError((error, stackTrace) {
return Text("Error");
});
}
希望这会有所帮助