firebase - Flutter/Firestore - 实时收听集合和子集合
问题描述
我有一个名为“reviews”的firebase 集合,其中包含一个子集合“clients”。
我希望从 Firebase Firestore 与他们的所有者实时获取所有评论,但在正确映射数据并返回听众的结果时我有点迷茫。
这是“评论”模型:
class Review {
final String reviewTitle;
final String reviewContent;
final String reviewCategory;
final String reviewTimestamp;
final int reviewVotesCount;
final Client client;
Review(
{this.reviewTitle,
this.reviewContent,
this.reviewCategory,
this.reviewTimestamp,
this.reviewVotesCount,
this.client});
}
这是服务类:
class ReviewService {
var currentUser = FirebaseAuth.instance.currentUser;
var firestoreInstance = FirebaseFirestore.instance;
List<Review> fetchAllThreads() {
Review review;
Client client;
List<Thread> mReviewsList = new List<Review>();
firestoreInstance.collection('reviews').snapshots().listen((result) {
result.docs.forEach((result) {
firestoreInstance
.collection('reviews')
.doc(result.id)
.collection('clients')
.get()
.then((result) {/*here I get the result.data()*/});
});
});
}
我得到后的问题result.data()
如何将它映射到我的模型,以便我可以将结果对象添加到mReviewsList
然后返回mReviewsList
?
解决方案
您可以在Review
类中添加工厂构造函数以从 Map 创建它,同样适用于Client
.
factory Review.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return Review(
reviewTitle: map['reviewTitle'],
reviewContent: map['reviewContent'],
reviewCategory: map['reviewCategory'],
reviewTimestamp: map['reviewTimestamp'],
reviewVotesCount: map['reviewVotesCount'],
client: Client.fromMap(map['client']),
);
}
如果你使用 VS Code,'Dart Data Class Generator' 扩展可以很方便,并且 pub.dev 中有多个代码生成包用于序列化和反序列化
现在代替您的评论,您可以这样做:
mReviewsList.add(Review.fromMap(result.data()));
更新:
根据 Doug 的评论,如果您想将数据映射到模型并返回流,您可以创建一个辅助函数,如下所示:
Stream<List<T>> collectionStream<T>({
@required String path,
@required T builder(Map<String, dynamic> data),
}) {
final reference = FirebaseFirestore.instance.collection(path);
final snapshots = reference.snapshots();
return snapshots
.map((snapshot) => snapshot.docs.map((snapshot) => builder(snapshot.data())).toList());
}
要使用它,只需按如下方式调用它:
final stream = collectionStream<Review>(path: "reviews", builder: (data) => Review.fromMap(data));
如果您只想获取一次数据,您也可以为此创建一个辅助函数:
Future<List<T>> getDocuments<T>({
String path,
@required T builder(Map<String, dynamic> data),
}) async {
final reference = FirebaseFirestore.instance.collection(path);
final snapshots = await reference.get();
final docs = snapshots.docs.map((doc) => builder(doc.data())).toList();
return docs;
}
并以相同的方式调用它:
final reviews = getDocuments<Review>(path: "reviews", builder: (data) => Review.fromMap(data));
推荐阅读
- javascript - 如何在 React JS 中创建相同的 URL 方案但不同的路由和组件
- php - 我将如何保护 /netdata 或 Laravel 的 Netdata?
- c++ - 将输出流上的“nullptr”格式化为十六进制地址,而不是“0”
- c# - 如何使用 C# 用富文本填充 PDF 表单?
- mysql - 我可以使用什么 SQL 查询来确定最近更新了哪些数据库?
- php - Symfony 4 - PhpUnit 代码覆盖率报告不完整
- react-redux - 无法在 React Redux 中仅访问一个对象键(所有其他键都可以)
- django - 列表中的Django打印循环索引
- sql - 多个外键oracle
- javascript - UnhandledPromiseRejectionWarning: TypeError: Assignment to constant variable.at deleteTodo