【发布时间】:2020-09-19 05:23:18
【问题描述】:
我正在努力从我的颤振应用程序中编写(并且还没有弄清楚如何阅读)firebase 中的嵌套地图。我正在编写一个费用跟踪器,其中类别列表存储在每个日志中。我可以在 firebase 之间映射、保存和检索原始字段,但我迷失的是尝试将类别和子类别的映射写入 firebase,然后如何读取它们。
解决类别和子类别本质上是相同的,所以我只介绍其中一个。另外,我目前将类别 ID 作为类别类本身的键和一部分,稍后我将从类本身中删除 Id,因为我认为这是不好的做法,它目前只是在其他地方帮助我。
我也一直在关注 BLOC 方法,所以我也有模型可以转换为实体来处理 firebase。
这是一个类别(我已经删除了不相关的信息,例如 props 和 to string):
<pre>
class MyCategory extends Equatable {
final String id;
final String name;
final IconData iconData;
MyCategory({@required this.id, @required this.name, this.iconData});
MyCategoryEntity toEntity() {
return MyCategoryEntity(
id: id,
name: name,
iconCodePoint: iconData.codePoint.toString(),
iconFontFamily: iconData.fontFamily,
);
}
static MyCategory fromEntity(MyCategoryEntity entity) {
return MyCategory(
id: entity.id,
name: entity.name,
iconData: IconData(int.parse(entity.iconCodePoint),
fontFamily: entity.iconFontFamily),
);
}
}
</pre>
该类别的模型实体具有 JsonSerialization 并且还使用 Icon codepoint/fontFamily,因为从 firebase 来回传递似乎比直接传递 IconData 更友好。
<pre>
@JsonSerializable()
class MyCategoryEntity extends Equatable {
final String id;
final String name;
final String iconCodePoint;
final String iconFontFamily;
const MyCategoryEntity(
{this.id, this.name, this.iconCodePoint, this.iconFontFamily});
factory MyCategoryEntity.fromJson(Map<String, dynamic> json) =>
_$MyCategoryEntityFromJson(json);
Map<String, dynamic> toJson() => _$MyCategoryEntityToJson(this);
</pre>
我认为您不需要将 Log 模型视为直接与 firebase 对话的 LogEntity。这是我完全卡住的地方。我已经看过一些如何传递对象列表的示例,但我似乎无法弄清楚如何传递对象映射。我也不确定如何将它从 firestore 读回 LogEntity(如下面的两个 TODO 所示)。
<pre>
class LogEntity extends Equatable {
final String uid;
final String id;
final String logName;
final String currency;
final bool active;
//String is the category id
final Map<String, MyCategory> categories;
final Map<String, MySubcategory> subcategories;
const LogEntity({this.uid, this.id, this.logName, this.currency, this.categories, this.subcategories, this.active});
static LogEntity fromSnapshot(DocumentSnapshot snap) {
return LogEntity(
uid: snap.data[UID],
id: snap.documentID,
logName: snap.data[LOG_NAME],
currency: snap.data[CURRENCY_NAME],
//TODO de-serialize categories and subcategories
active: snap.data[ACTIVE],
);
}
Map<String, Object> toDocument() {
return {
UID: uid,
LOG_NAME: logName,
CURRENCY_NAME: currency,
//TODO serialize categories and subcategories, this does doesn't work
CATEGORIES: categories.map((key, value) => categories[key].toEntity().toJson()).toString(),
ACTIVE: active,
};
}
}
</pre>
我真的希望对此有所帮助,因为我能够理解的唯一示例是列表,而不是地图。另外我想在这个应用程序的几个地方使用类似的方法,所以弄清楚这一点至关重要。
【问题讨论】:
-
您是否尝试过使用
Map<String, MyCategory>.from()和Map<String, MySubcategory>.from()从快照数据中获取地图? -
此外,Firebase 仅支持有限数量的类型(如数字、字符串、数组等)。您需要对您的类别和子类别进行
.map()调用,以将它们转换为Map<String, Map<...>>,例如categories.map((key, value) => MapEntry(key, <call your toJson here from value>)) -
我刚刚注意到您的 toDocument() 类别末尾有一个 toString()。除非它作为字符串存储在 firebase 中,否则您不应该拥有它。此外,
categories[key]是多余的;简单地使用价值。 -
谢谢@GregoryConrad!我设法通过以下方法将数据导入firebase,但我仍然不知道如何检索它。
CATEGORIES: categories.map((key, value) => MapEntry(key, value.toEntity().toJson())),和SUBCATEGORIES: subcategories.map((key, value) => MapEntry(key, value.toEntity().toJson())), -
当然。我会把这一切都放在一个答案中。