Flutter UI在呈现之前不等待值
我正在尝试开发一款Fatterandroid应用程序,它将与云Firestore数据库进行通信。我希望它遍历一系列引用中的每个文档,从每个文档中获取一个值,从读取的值中增加一个计数器,并将其作为文本小部件返回。问题是,读取的值似乎没有反映在UI中,尽管我可以从云中读取的值正确打印出计数器 我尝试使用StreamBuilder和FutureBuilder。我最后一次尝试是让我的函数返回一个Future,并等待读取该值,但没有成功。UI上反映的只是未来的实例Flutter UI在呈现之前不等待值,flutter,dart,Flutter,Dart,我正在尝试开发一款Fatterandroid应用程序,它将与云Firestore数据库进行通信。我希望它遍历一系列引用中的每个文档,从每个文档中获取一个值,从读取的值中增加一个计数器,并将其作为文本小部件返回。问题是,读取的值似乎没有反映在UI中,尽管我可以从云中读取的值正确打印出计数器 我尝试使用StreamBuilder和FutureBuilder。我最后一次尝试是让我的函数返回一个Future,并等待读取该值,但没有成功。UI上反映的只是未来的实例 Future<double>
Future<double> calculatePrice(DocumentSnapshot pedido) async{
priceWrapper wrapper = priceWrapper(0);
for (DocumentReference d in pedido.data['requested_products']) {
d.get().then( (f) {
wrapper.value += f['value'];
print(wrapper.value);
});
}
print(wrapper.value);
return wrapper.value;
}
Widget buildListItem(BuildContext context, DocumentSnapshot document) {
return ListTile(
//...
trailing: Text("${calculatePrice(document)}",
style: Theme.of(context).textTheme.subtitle,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: CustomDrawer(
context: context,
),
appBar: AppBar(
title: Text("Requests"),
),
body: Container(
//...
child: StreamBuilder(
stream: Firestore.instance.collection("currentRequests").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
if (snapshot.hasError) {
print("SNAPSHOT ERROR: ${snapshot.error}");
}
return LinearProgressIndicator();
}
return ListView.separated(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return buildListItem(context, snapshot.data.documents[index]);
},
);
},
),
),
);
}
printwrapper.value调用打印期望值,但该值不会显示在UI中。在calculatePrice函数中放入等待
for (DocumentReference d in pedido.data['requested_products']) {
await d.get().then( (f) {
wrapper.value += f['value'];
print(wrapper.value);
});
}
同样,被归还的是一个未来,而不是一个双倍的未来
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");
});
}
希望这对您有所帮助您必须使用FutureBuilder,它仅在calculatePrice方法完成后才会呈现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,
);
}
}
);
}
在下面的示例中,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,
);
}
}
);
}
get方法是异步的,不会中断执行流。INSTEAN将在中注册回调,然后在get完成时调用该回调。由于执行流没有中断,for循环将迭代所有数据。然后,将执行最后一条print语句。
稍后,将调用回调
由于代码没有中断,您的calculatePrice方法将有效地非常快地完成,但结果是priceWrapper0是wrapper的初始值。这就是将用于创建ListTile的值,以及它似乎不起作用的原因
使用FutureBuilder允许您在完成所有异步工作后管理应用程序的呈现。您需要一个FutureBuilder作为后续属性的小部件使用异步请求强制UIYes,我的问题实际上是由于FutureBuilder的使用不正确。谢谢你的意见!