我在StreamBuilder中有一个Listview.builder()。在Listview构建器中,我需要为Firestore中的每个项目获取数据,然后显示数据。但是因为查看数据库是一个Future操作,所以我需要await方法来等待数据并在之后显示。
这是我的代码,我创建了两个不同的类。
头等舱:
StreamBuilder getFriends() {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection("Users")
.doc(AuthFunc().currentUser!.uid)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
log("${snapshot.data["Contact"]}");
List list = snapshot.data["Contact"];
friends = list;
return ListviewSharedWidget(
friends: friends, year: widget.year, idDay: widget.idDay);
}
return Container();
},
);
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: 450,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: 400,
child: getFriends(),
)
],
),
);
第二类:
@override
void initState() {
year = widget.year;
idDay = widget.idDay;
friends = widget.friends;
_getText();
super.initState();
}
Future<void> _getText() async {
await FirebaseFirestore.instance
.collection("Users")
.doc(AuthFunc().currentUser!.uid)
.get()
.then((value) {
textEditingController.text = value["Answers"]["$year"]["$idDay"]["text"];
});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: friends.length + 1,
itemBuilder: (context, index) {
String name = ""; // This variable causing problem
TextEditingController controller = TextEditingController();
FirebaseFirestore.instance
.collection("Users")
.doc(friends[index - 1])
.get()
.then(
(value) {
name = value["Name"]; // Here I update the variable
controller.text = value["Answers"]["$year"]["$idDay"]["text"];
},
);
return Center(
child: Column(
children: [
TextFieldSharedWidget(
controller: controller, // But this variable is well updated and the text
// is displayed
name: name, // But when I use here, the variable is still empty
currentUser: false,
),
const SizedBox(
height: 20,
)
],
),
);
}
);
}
如果每个条目都需要从数据库异步加载另一个文档,请考虑将该加载操作包装在FutureBuilder
中。它可能看起来有点奇怪,但请记住,FutureBuilder
只是另一个小部件像任何其他-所以它通常工作得很好,即使你有一个列表。
比如:
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: friends.length + 1,
itemBuilder: (context, index) {
return FutureBuilder(
future: FirebaseFirestore.instance
.collection("Users")
.doc(friends[index - 1])
.get(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("ERRor: ${snapshot.error}");
}
if (snapshot.hasData) {
return Text(snapshot.data!.child("Name").value);
}
return CircularLoadingIndicator();
},
);
}
);
}
注意:我没有测试上面的代码,所以请尝试自己修复语法和一些小问题。
避免加载所有这些单独文档的常见方法是在原始文档中复制所需的数据。例如,如果您不仅存储每个朋友的UID,还存储他们的名字,那么您就可以显示整个朋友列表,而无需加载所有单独的朋友的文档。
在处理NoSQL数据库时,这种类型的数据复制非常常见。如果您是这个领域的新手,我建议您查看NoSQL数据建模和了解Cloud Firestore。