下面是我用来解析Firestore数据的代码(注释部分是我解析嵌套列表的原始方式)。正常情况下,我使用map
和.toList()
是成功的,但在我开始使用抽象和具体类之后,.toList()
不断抛出错误。我发现List.from
起作用了,但我不明白为什么。如果有人能帮助我理解两者之间的区别,并就何时使用它们提出建议,我将非常感谢你能分享的任何知识。
factory Story.fromMap(Map data) {
if (data == null) {
throw FormatException("Null JSON provided to Story class");
}
try {
return Story(
title: data['title'] ?? '',
type: data['type'] ?? 'standard',
audioRef: data['audioRef'] == null ? null : TourAsset(data['audioRef']),
videoRef: TourAsset(data['videoRef']),
animationRef: TourAsset(data['animationRef']),
posterImgRef: TourAsset(data['posterImgRef']),
storyImages: data["storyImages"] == null
? null
: List<StoryImage>.from(
data["storyImages"].map(
(x) => StoryImage.fromMap(x),
),
),
// storyImages: data['storyImages'] == null
// ? null
// : data['storyImages']
// .map(
// (Map<String, dynamic> eachImage) =>
// StoryImage.fromMap(eachImage),
// )
// .toList(),
ownerId: data['ownerId'] ?? '',
storyId: data['storyId'] ?? '',
tags: data["tags"] == null
? null
: List<String>.from(
data["tags"].map((x) => x),
),
// tags: data['tags'] == null
// ? [] as List<String>
// : data['tags'].map((item) => item as String).toList(),
);
} catch (e) {
print(e);
throw FormatException("Error parsing Story class");
}
}
下面是另一个成功的尝试。在其中,我将storyImages分配给一个局部变量,并在映射列表之前进行空检查。
factory Story.fromMap(Map data) {
if (data == null) {
throw FormatException("Null JSON provided to Story class");
}
try {
final storyImages = data["storyImages"];
final List<StoryImage> storyImagesList = [];
if (storyImages != null) {
for (var story in storyImages) {
storyImagesList.add(StoryImage.fromMap(story));
}
}
return Story(
title: data['title'] ?? '',
type: data['type'] ?? 'standard',
audioRef: data['audioRef'] == null ? null : TourAsset(data['audioRef']),
videoRef: TourAsset(data['videoRef']),
animationRef: TourAsset(data['animationRef']),
posterImgRef: TourAsset(data['posterImgRef']),
storyImages: storyImagesList,
ownerId: data['ownerId'] ?? '',
storyId: data['storyId'] ?? '',
tags: data["tags"] == null
? null
: List<String>.from(data["tags"].map((x) => x)),
);
} catch (e) {
print(e);
throw FormatException("Error parsing Story class");
}
}
List.from
是一个使用现有可迭代对象的元素创建新列表的方法。语法为:
List.from(iterable, [growable = true])
iterable是从中获取元素的源可迭代对象。可生长的是一个可选参数,用于指定列表是否可增长。如果将其设置为true(默认值),则该列表是可增长的,并且可以向其中添加新元素。如果设置为false,则该列表是固定长度的,不能添加新元素。
List.from
是有用的,当你想从一个现有的可迭代对象创建一个新的列表,你想指定新的列表是否可增长。
另一方面,.toList()
是一个将可迭代对象转换为列表的方法。语法为:
iterable.toList()
iterable要转换为列表的源可迭代对象。
.toList()
在您想要将可迭代对象转换为列表并且不需要指定新列表是否可生长时非常有用。新列表将具有与原始可迭代对象相同的可扩展性。
在您提供的代码中,您使用List.from
从data["storyImages"]
可迭代对象创建一个新列表。这是因为data["storyImages"]
是一个映射列表,而您希望通过在data["storyImages"]
列表的每个元素上使用StoryImage.fromMap
工厂构造函数来创建一个新的StoryImage
对象列表。
在注释部分,您使用.toList()
将data['storyImages']
可迭代对象转换为列表。然而,这在本例中是不必要的,因为data['storyImages']
已经是一个列表。您可以简单地对data['storyImages']
列表的每个元素使用StoryImage.fromMap
工厂构造函数,而无需先将其转换为列表。