在flutter中使用来自firebase的数据构建小部件,返回空小部件



这是我尝试过的代码,但每次运行它都会返回一个空小部件。似乎列表在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的asyncawait关键字使上述内容更熟悉:

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

相关内容

  • 没有找到相关文章

最新更新