我正在努力从我的 flutter 应用程序编写(并且还没有弄清楚如何读取)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>
Run Code Online (Sandbox Code Playgroud)
该类别的模型实体具有 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>
Run Code Online (Sandbox Code Playgroud)
我认为您不需要看到 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>
Run Code Online (Sandbox Code Playgroud)
我真的希望对此有所帮助,因为我能够理解的唯一示例是列表,而不是地图。我也想在这个应用程序的几个地方使用类似的方法,所以弄清楚这一点至关重要。
Firebase 需要一个Map<String, dynamic>,其中 dynamic 是其支持的类型之一(如字符串、数字、地图、数组等)。因此,如果您有一个自定义对象,例如MyCategory在您的示例中,您需要将.map()其设置为支持的类型之一(Map<String, dynamic>在本例中为另一个)。因此,您可以执行<map that you need to convert>.map((key, value) => MapEntry(key, <method to convert each value to a Map<String, dynamic>>)). 您的示例几乎是正确的,但它有一个toString()将使 Firebase 将其存储为字符串,而不是地图(这不是所需的行为)。正如评论中所讨论的,删除toString()应该可以解决该问题。
与导出数据类似,Firebase 将为您提供一个Map<String, dynamic>where dynamic 是 Firebase 支持的类型之一,对于类别和子类别再次Map<String, dynamic>是 s。因此,您需要将snap.data[KEY]动态的转换为Map<String, YourObject>代码中相应类型的 。解析这个的步骤是这样的:
.map() 将此转换为您自己的类型的数据因此,类似以下内容应该有效:
return LogEntity(
uid: snap.data[UID],
id: snap.documentID,
logName: snap.data[LOG_NAME],
currency: snap.data[CURRENCY_NAME],
categories: (snap.data[CATEGORIES] as Map<String, dynamic>).map((key, value) => MapEntry(key, MyCategory.fromEntity(MyCategoryEntity.fromJson(value)))),
// todo subcategories should follow the same form as categories; I will leave that one up to you
active: snap.data[ACTIVE],
);
Run Code Online (Sandbox Code Playgroud)
我想在这里做笔记,以及万一有人发现了如何解析嵌套图/列表,从火力地堡使用原始类型(如这一问题的搜索Map<String, String>,Map<String, int>或者List<String>仅举几例)。在这种情况下,检查Map<String, PrimitiveType>.from()和List<PrimitiveType>.from()构造函数;假设它们PrimitiveType是 Firebase 支持的类型之一,它们可能会完全按照您的要求执行。如果没有,请参阅上面的答案。
还有一件小事:我没有查看你所有的代码,但我忍不住注意到的一件事是你的static LogEntity fromSnapshot(). 在 Dart 中,您通常会根据用例使用工厂或命名构造函数,但我绝不是专家。
| 归档时间: |
|
| 查看次数: |
1666 次 |
| 最近记录: |