我尝试搜索其他问题,但是与此类似的唯一问题是在JavaScript中给出了答案,而不是Dart / Flutter。我正在尝试以List<BaseModel>
到目前为止,与我在网上搜索的内容相去甚远,我认为DataSnapshot
的结果是我可以解析的地图,因此我尝试了一下,但遇到了以下错误:List<dynamic>' is not a subtype of type 'Map<dynamic, dynamic>
>
我的代码:
Future<List<BaseModel>> getList(
{DatabaseReference query, Models modelType}) async {
List<BaseModel> list = new List();
DataSnapshot snap = await query.once();
Map<String, dynamic> json = Map.from(snap.value);
json.forEach((key, value) {
list.add(BaseModel(model: modelType, key: key, snapshot: value));
});
return list;
}
奇怪的是,即使我尝试解析非列表模型,我也会遇到相同的错误。
我的数据库结构如下:
更新:
BaseModel:
abstract class BaseModel {
factory BaseModel({Models model, String key, Map map}) {
switch (model) {
case Models.MyModel:
return MyMod.fromSnapshot(key: key, map: map);
break;
default:
throw ("Not a valid model.");
}
}
}
MyModel:
MyModel.fromSnapshot({String key, Map map}) {
_id = key;
_title = map['title'];
}
我的Firebase查询只是带有.child("Root")
的数据库引用
答案 0 :(得分:0)
我也有类似的经历,其中snapshot.value有时返回一个列表,有时返回一个Map。我搜索了很长时间,但没有运气,但我想出了一种解决方法。 我怀疑问题是由使用值为零的记录键引起的,因此我在将每个键添加到db之前将其添加了100,然后在读取并处理记录时将其减去。问题消失了,然后我总是得到了地图。 从那以后,我已经看到了这种现象的原因,它证实了零键值是罪魁祸首,但是不幸的是我没有保存链接。我认为它是在Firebase博客之一上。 我认为0记录返回一个列表,而具有正值的记录返回一个Map。 无论如何,请尝试添加100的技巧,然后看看会有所帮助。如果有帮助,请支持我。...我认为您不需要添加或删除100的代码。:-)
找到这篇文章,Firebase正在根据快照内容决定是否应该渲染数组或地图:https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html?m=1
更新:
对不起,我的“从0开始”理论是一条红鲱鱼。
此行为的关键(粗体中的位)在Firebase博客的一部分(上面的链接)中指出:
但是,当您需要帮助在Firebase中存储阵列的人员时, 调用.val()或使用REST api读取数据,如果数据看起来像 一个数组,Firebase会将其呈现为一个数组。
尤其是,如果所有键都是整数,并且一半以上 0和对象中最大键之间的键为非空 值,然后Firebase会将其呈现为数组。 重要的是要记住。
///我们发送此['a','b','c','d','e'] // Firebase存储此{0: 'a',1:'b',2:'c',3:'d',4:'e'}
//由于键是数字键和顺序键,//如果我们查询数据, 我们得到这个['a','b','c','d','e']
//,但是,如果我们随后删除a,b和d,则//它们不再 大多是顺序的,所以//我们不会返回数组{2:'c',4:'e'} 您目前无法更改或阻止此行为。
我现在已经通过设置一个如下图所示的db节点来对此进行了测试。我使用snapshot.value
和snapshot.value is List
测试了snapshot.value is Map
中返回的内容,它们都返回true或false。
仅存在节点0、1和3时,Firebase RTDB会很高兴地在snapshot.value
中返回一个列表。当我添加数据不一致的节点4和6时,它决定是时候返回Map了。 :-)
因此,快速的解决方案是使用is List
和/或is Map
测试snapshot.value的内容,然后进行相应的处理,否则请重新考虑您的密钥...事实是问题是顺序的或接近顺序的(有间隙),但子结构相同。
答案 1 :(得分:0)
我找到了解决方法!
我的新代码:
Future<List<BaseModel>> getList({DatabaseReference query, Models modelType}) async {
List<BaseModel> list = new List();
DataSnapshot snap = await query.once();
List<dynamic> resultList = snap.value;
for(var i = 0; i < resultList.length; i++) {
Map<dynamic, dynamic> map = Map.from(resultList[i]);
list.add(BaseModel(model: modelType, key: i.toString(), snapshot: map));
}
return list;
}
假设您从模型的.fromMap(yourMap)
构造函数方法中解析值,这应该可以工作。像_title = yourMap['key'];