Flutter Firestore 如何从存储的Map中获取每个训练条目的独立Stream
实现方案
你当前代码只返回单个CalendarEvent的原因是:你监听的是完整的trainings文档,转换时直接把整个文档数据传入工厂构造函数,所以只会生成1个对象。要拿到Map内每个训练条目的对应结果,可按需选择以下两种方案:
方案1:返回Stream<List<CalendarEvent>>(绝大多数场景的最优选择)
该方案会监听trainings文档的所有变更,每次文档更新时自动把所有训练条目转换成列表推送,无需单独维护多个流。
第一步:调整工厂构造函数
修改CalendarEvent.fromJson,适配单个训练条目的数据解析,同时把Map的key作为条目ID传入:
// 从单个训练条目的数据生成CalendarEvent对象 factory CalendarEvent.fromJson(String entryId, Map<dynamic, dynamic> json) { return CalendarEvent( title: json['title'] ?? '无标题', id: entryId, date: json['date'] ?? '无日期', ); }
第二步:修改Stream转换逻辑
把原来的单对象转换改成遍历Map生成列表:
Stream<List<CalendarEvent>> getTrainings() { return _firestore .collection('users') .doc('${_authentication.getUID()}') .collection('user') .doc('trainings') .snapshots() .map((doc) { // 直接取文档所有字段作为训练条目Map(和你存储结构匹配) final Map trainingsMap = doc.data() ?? {}; // 遍历Map的每个键值对,生成CalendarEvent列表 return trainingsMap.entries.map((entry) => CalendarEvent.fromJson(entry.key, entry.value) ).toList(); }); }
方案2:单个训练条目专属Stream
如果你确实需要单独监听某一个训练条目的变更,可以用以下方法,传入要监听的条目标识(即Map的key)即可:
Stream<CalendarEvent?> getSingleTrainingStream(String entryKey) { return _firestore .collection('users') .doc('${_authentication.getUID()}') .collection('user') .doc('trainings') .snapshots() .map((doc) { final Map trainingsMap = doc.data() ?? {}; final entryData = trainingsMap[entryKey]; if (entryData == null) return null; return CalendarEvent.fromJson(entryKey, entryData); }); }
注意事项
- 你当前的
toMap方法没有返回值,实际使用时需要补上return map; - 如果你的训练条目数量很大,建议不要存在单个文档的Map中,Firestore单文档有1M大小限制,条目过多会触发上限,这种场景可以把训练条目改成子集合存储。
内容的提问来源于stack exchange,提问作者LazyTurtle
相关产品推荐
相关产品推荐

