这是我尝试过的代码,但每次运行它都会返回一个空小部件。似乎列表在then()调用结束时被清空。
final database = FirebaseDatabase.instance.reference();
final reviews = database.child("books/12345/reviews");
Widget getReviewCards(DatabaseReference reviews) {
List<Widget> reviewList = <Widget>[];
reviews.once().then((DataSnapshot snapshot) {
final data = new Map<dynamic, dynamic>.from(snapshot.value);
data.forEach((key, value) {
reviewList.add(new ReviewCard(stars: 2, reviewText: value.toString(), username: key));
});
});
return Column(children: reviewList);
}
有谁知道怎么回事吗?
数据是从Firebase(和大多数现代云api)异步加载的,这导致你的代码没有按照你期望的顺序执行。添加一些日志记录使这更容易看到:
print('Before loading data');
reviews.once().then((DataSnapshot snapshot) {
print('Loaded data');
});
print('After loading data');
如果你运行这段代码,你将得到:
加载数据前
加载数据后
加载数据
这可能不是您所期望的,但它确实完美地解释了为什么您的小部件是空的:当您返回小部件时,没有任何reviewList.add(...)
调用发生。
不是返回一个Widget
,你将不得不返回一个Future<Widget>
,这是在未来返回一个小部件的承诺:
Future<Widget> getReviewCards(DatabaseReference reviews) { // 👈 Change return type
return reviews.once().then((DataSnapshot snapshot) { // 👈 Add return
final data = new Map<dynamic, dynamic>.from(snapshot.value);
List<Widget> reviewList = <Widget>[];
data.forEach((key, value) {
reviewList.add(new ReviewCard(stars: 2, reviewText: value.toString(), username: key));
});
return Column(children: reviewList); // 👈 Moved up
});
}
您还可以使用Dart的async
和await
关键字使上述内容更熟悉:
Future<Widget> getReviewCards(DatabaseReference reviews) async {
DataSnapshot snapshot = await reviews.once();
final data = new Map<dynamic, dynamic>.from(snapshot.value);
List<Widget> reviewList = <Widget>[];
data.forEach((key, value) {
reviewList.add(new ReviewCard(stars: 2, reviewText: value.toString(), username: key));
});
return Column(children: reviewList);
}
如果你想在你的UI中显示这个小部件,你需要把它包装在一个FutureBuilder
.
也看到:
- 异步编程:futures, async, await