flutter - Flutter - 从 Cloud Firestore 读取嵌套地图
问题描述
我在尝试从 Cloud Firestore 读取另一张地图中的地图时遇到问题。我在互联网上找到了几篇关于这个主题的帖子,但作为 Flutter 和 Firebase 的初学者,我无法让这些案例适应我的情况。
在 Firebase Firestore 中,我有以下数据示例,属于“媒体”集合:
我能够读取几乎所有数据,包括数组(使用演员表),但“成分”真的让我很痛苦。它是一个Map<String, Quantity>
,数量是我的一个类:
class Quantity {
final double amount;
final String unit;
const Quantity({
required this.amount,
required this.unit,
});
String toString() => '$amount $unit';
}
现在它很简单,但会随着更多使用双精度值的方法而增长。这就是我不想摆脱它并简化数据库条目的原因。
我需要使用 Stream Builder 读取所有数据并将其传递给 ListView.buider,如下所示:
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('media')
.orderBy('initials')
.snapshots(),
builder: (BuildContext ctx,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> media) {
if (media.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
var docs = media.data!.docs;
var box = Hive.box<Favorite>('favorites');
return ListView.builder(
itemCount: media.data!.docs.length,
itemBuilder: (ctx, i) {
Medium md = Medium(
initials: docs[i].get('initials'),
longName: docs[i].get('longName'),
ingredients: <String, Quantity>{}, // docs[i].get('ingredients'),
steps: docs[i].get('steps').cast<String>(),
mediumState: PhysicalState.values.elementAt(
docs[i].get('mediumState'),
),
reference: docs[i].data().containsKey('reference')
? docs[i].get('reference')
: '',
isComplement: docs[i].data().containsKey('isComplement')
? docs[i].get('isComplement')
: false,
ps: docs[i].data().containsKey('ps') ? docs[i].get('ps') : '',
);
if (box.get(docs[i].get('initials')) == null) {
box.put(
docs[i].get('initials'),
Favorite(
initials: docs[i].get('initials'),
isFavorite: false,
),
);
}
return MediumCard(
medium: md,
);
},
);
},
);
}
被调用的 Medium 构造函数是这个:
class Medium {
final String initials;
final String longName;
final Map<String, Quantity> ingredients;
final List<String> steps;
final PhysicalState mediumState;
String reference;
bool isComplement;
String ps;
Medium({
required this.initials,
required this.longName,
required this.ingredients,
required this.steps,
required this.mediumState,
this.reference = '',
this.isComplement = false,
this.ps = '',
});
}
我可以发布很多尝试和错误消息,但帖子会不必要地长,所以只有一次尝试,尝试使用与其他条目相同的逻辑docs[i].get('ingredients')
,这给了我这个:
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<String, Quantity>'
重要的是要注意,“成分”中的数量 os 数量可能会有所不同,并且并不总是与上述示例中的两个相同(水和琼脂)。
所以最后,这个问题。如何调整ListView.builder
代码中“成分”的导入以正确读取 Firebase 中的那部分数据?
我在Flutter 2.2.3
,cloud_firestore: ^2.4.0
并且firebase_core: ^1.4.0
Ps.:如有英文错误,请见谅。我不是母语人士(“作家”)。
解决方案
经过更多的尝试和失败后,我能够通过添加ListView.builder
代码来解决我的问题:
var docs = media.data!.docs;
var box = Hive.box<Favorite>('favorites');
Map<String, Quantity> myIngredients = {};
return ListView.builder(
itemCount: media.data!.docs.length,
itemBuilder: (ctx, i) {
// Convert data from firebase into <String, Quantity>
Map.from(docs[i].get('ingredients')).entries.forEach((e) {
myIngredients[e.key] = Quantity(
amount: e.value['amount'].toDouble(),
unit: e.value['unit'],
);
});
Medium md = Medium(
initials: docs[i].get('initials'),
longName: docs[i].get('longName'),
ingredients: myIngredients,
steps: docs[i].get('steps').cast<String>(),
mediumState: PhysicalState.values.elementAt(
docs[i].get('mediumState'),
),
reference: docs[i].data().containsKey('reference')
? docs[i].get('reference')
: '',
isComplement: docs[i].data().containsKey('isComplement')
? docs[i].get('isComplement')
: false,
ps: docs[i].data().containsKey('ps') ? docs[i].get('ps') : '',
);
因此,使用Map.from
方法我能够设置一个Map<String, Quantity>
实例并使用它。
如果有人找到更好、更清洁的解决方案,我很想看看。非常感谢。