Flutter Firestore - 检索仅属于一组特定 ID 的文档快照并在屏幕上显示该数据
Flutter Firestore - To retrieve document snapshots belonging to only a certain set of ids and show that data on screen
我正在传递我的 Firestore 文档 ID 的构造函数列表,我只想在我的 'LinksData' collection.
中检索和显示属于这些 ID 的数据
所以基本上我想检索属于我的另一个列表中的所有文档的文档快照(我正在将其传递给构造函数)。
我想到了两种方法:
- 使用 StreamBuilder,但据我所知,有了这个我将在我的 collection 中获取所有文档快照,或者只获取一个。
- 使用 Future Builder,我做了以下功能,但是当我使用它时,它显示以下错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform
我该怎么做?我不想使用流生成器检索所有文档,因为那会影响我的日常阅读。
这是我尝试使用 FutureBuilder 的代码。
FutureBuilder<List<LinkCards>>(
future: generateList(widget.linksDataIds),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Oops! Some Error Occurred!'));
} else {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 220,
mainAxisSpacing: 12.0,
),
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return snapshot.data![index];
});
}
},
)
这是我的 Future 函数
Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
FirebaseFirestore fireStore = FirebaseFirestore.instance;
List<LinkCards> listCards = [];
listLinksDataId.forEach((linkDataId) async {
print(linkDataId);
await fireStore
.collection('LinksData')
.doc(linkDataId)
.get()
.then((value) => {
listCards.add(LinkCards(
link: value.get('link'),
linkTitle: value.get('title'),
linkImage: value.get('image'),
relatedCategories: value.get('categories'),
platform: value.get('platform'),
))
});
});
return listCards;
}
这是我的数据库结构的图像:enter image description here
这就是您的函数的理想外观。
试一试,希望它能奏效。
Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
FirebaseFirestore fireStore = FirebaseFirestore.instance;
List<LinkCards> listCards = [];
for(int i=0; i<listLinksDataId.length;i++){
final firestoreResult = await fireStore
.collection('LinksData')
.doc(linkDataId)
.get();
listCards.add(
link: firestoreResult.data()["link"],
linkTitle: firestoreResult.data()["title"],
linkImage: firestoreResult.data()["image"],
relatedCategories: firestoreResult.data()["categories"],
platform: firestoreResult.data()["platform"],
);
}
return listCards;
}
这是我通常采用的方法,希望对您也有用。
这应该让你很接近。这是一个我可以重现的简化示例,它只使用一个字符串列表。
Future<List<String>> generateList(List<String> listLinksDataId) async {
List<String> listCards = [];
final collection = FirebaseFirestore.instance.collection('LinksData');
for (String docId in listLinksDataId) {
final snapshot = await collection.doc(docId).get();
// snapshot is the document snapshot whose id
// matches the index in the list you're passing in
final linksData = snapshot['linksData']; // list of ids in linksData field
for (var i = 0; i < linksData.length; i++) { // looping through list
final field = linksData[i];
listCards.add(field);
}
}
return listCards;
}
这将至少 return linksData
字段中的所有 ID 仅在与您传入的列表索引匹配的文档中。
您应该能够设置一个快速测试页面和一个 FutureBuilder<ListString>>
并将此方法作为 Future
传递。
Return 一个 ListView
只显示文本小部件,您会看到您想要的所有 ID。
Expanded(
child: ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) =>
Text(snapshot.data![index])),
);
然后您可以从那里修改以完全填充您的 LinkCard
。
感谢您的回复,但我通过稍微修改我的数据库找到了解决方案。
在 'LinksData' 集合中,我放置了一个包含所有类别的字段(类型数组)。然后我像这样使用 StreamBuilder :
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('LinksData')
.where('categories', arrayContains: widget.categoryName)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('${snapshot.error}'));
} else {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 220,
mainAxisSpacing: 12.0,
),
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
return LinkCards(
linkImage: snapshot.data!.docs[index].get('image'),
linkTitle: snapshot.data!.docs[index].get('name'),
link: snapshot.data!.docs[index].get('link'),
relatedCategories: snapshot.data!.docs[index].get('categories'),
platform: snapshot.data!.docs[index].get('platform'));
});
}
},
)
我正在传递我的 Firestore 文档 ID 的构造函数列表,我只想在我的 'LinksData' collection.
中检索和显示属于这些 ID 的数据所以基本上我想检索属于我的另一个列表中的所有文档的文档快照(我正在将其传递给构造函数)。
我想到了两种方法:
- 使用 StreamBuilder,但据我所知,有了这个我将在我的 collection 中获取所有文档快照,或者只获取一个。
- 使用 Future Builder,我做了以下功能,但是当我使用它时,它显示以下错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform
我该怎么做?我不想使用流生成器检索所有文档,因为那会影响我的日常阅读。
这是我尝试使用 FutureBuilder 的代码。
FutureBuilder<List<LinkCards>>(
future: generateList(widget.linksDataIds),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Oops! Some Error Occurred!'));
} else {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 220,
mainAxisSpacing: 12.0,
),
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return snapshot.data![index];
});
}
},
)
这是我的 Future 函数
Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
FirebaseFirestore fireStore = FirebaseFirestore.instance;
List<LinkCards> listCards = [];
listLinksDataId.forEach((linkDataId) async {
print(linkDataId);
await fireStore
.collection('LinksData')
.doc(linkDataId)
.get()
.then((value) => {
listCards.add(LinkCards(
link: value.get('link'),
linkTitle: value.get('title'),
linkImage: value.get('image'),
relatedCategories: value.get('categories'),
platform: value.get('platform'),
))
});
});
return listCards;
}
这是我的数据库结构的图像:enter image description here
这就是您的函数的理想外观。 试一试,希望它能奏效。
Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
FirebaseFirestore fireStore = FirebaseFirestore.instance;
List<LinkCards> listCards = [];
for(int i=0; i<listLinksDataId.length;i++){
final firestoreResult = await fireStore
.collection('LinksData')
.doc(linkDataId)
.get();
listCards.add(
link: firestoreResult.data()["link"],
linkTitle: firestoreResult.data()["title"],
linkImage: firestoreResult.data()["image"],
relatedCategories: firestoreResult.data()["categories"],
platform: firestoreResult.data()["platform"],
);
}
return listCards;
}
这是我通常采用的方法,希望对您也有用。
这应该让你很接近。这是一个我可以重现的简化示例,它只使用一个字符串列表。
Future<List<String>> generateList(List<String> listLinksDataId) async {
List<String> listCards = [];
final collection = FirebaseFirestore.instance.collection('LinksData');
for (String docId in listLinksDataId) {
final snapshot = await collection.doc(docId).get();
// snapshot is the document snapshot whose id
// matches the index in the list you're passing in
final linksData = snapshot['linksData']; // list of ids in linksData field
for (var i = 0; i < linksData.length; i++) { // looping through list
final field = linksData[i];
listCards.add(field);
}
}
return listCards;
}
这将至少 return linksData
字段中的所有 ID 仅在与您传入的列表索引匹配的文档中。
您应该能够设置一个快速测试页面和一个 FutureBuilder<ListString>>
并将此方法作为 Future
传递。
Return 一个 ListView
只显示文本小部件,您会看到您想要的所有 ID。
Expanded(
child: ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) =>
Text(snapshot.data![index])),
);
然后您可以从那里修改以完全填充您的 LinkCard
。
感谢您的回复,但我通过稍微修改我的数据库找到了解决方案。 在 'LinksData' 集合中,我放置了一个包含所有类别的字段(类型数组)。然后我像这样使用 StreamBuilder :
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('LinksData')
.where('categories', arrayContains: widget.categoryName)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('${snapshot.error}'));
} else {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 220,
mainAxisSpacing: 12.0,
),
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
return LinkCards(
linkImage: snapshot.data!.docs[index].get('image'),
linkTitle: snapshot.data!.docs[index].get('name'),
link: snapshot.data!.docs[index].get('link'),
relatedCategories: snapshot.data!.docs[index].get('categories'),
platform: snapshot.data!.docs[index].get('platform'));
});
}
},
)