Flutter firebase_database获取子项

时间:2019-02-14 22:03:50

标签: firebase firebase-realtime-database flutter

嗨,我想将快照从实时数据库反序列化到 Company 对象,并将其添加到 _companies 列表中。 但是我一直遇到错误...

这是我到目前为止所拥有的:

  List<Company> _companies = [];
  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    getItems().then((list){
      print("Now the list is here");

      setState(() {
        for (int i=0; i < list.length; i++) {
          Map<String, dynamic> map = list[i];

          Company company = new Company.fromMap(map);
          _companies.add(company);
        }
      });

    });
  }

  static Future<List> getItems( ) async {
    Completer<List> completer = new Completer<List>();

    FirebaseDatabase.instance
        .reference()
        .child("Companies")
        .once()
        .then( (DataSnapshot snapshot) {

      List map = snapshot.value; //It fails here
      completer.complete(map);
    } );

    return completer.future;
  }

这是我的公司课程:

class Company {
  String key;
  String category;
  String company_name;
  String company_url;
  String country;
  String description;
  String email;
  String faq_url;
  String instagram_url;
  String logo_url_image;
  String p_category;
  String parent_company_ok;
  String timestamp;

  Company();

  Company.fromSnapshot(DataSnapshot snapshot)
      : key = snapshot.key,
      category = snapshot.value['category'],
      company_name = snapshot.value['company_name'],
      company_url = snapshot.value['company_url'],
      country = snapshot.value['country'],
      description=  snapshot.value['description'],
      email = snapshot.value['email'],
      faq_url = snapshot.value['faq_url'],
      instagram_url = snapshot.value['instagram_url'],
      logo_url_image = snapshot.value['logo_url_image'],
      p_category = snapshot.value['p_category'],
      parent_company_ok = snapshot.value['parent_company_ok'],
      timestamp = snapshot.value['timestamp'];
}

但是,它在List map = snapshot.value; getItems()中失败。带有例外:_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'List<dynamic>'

如果任何人都可以提供用于在列表小部件中显示孩子的代码,我将非常高兴:)

这是我在Firebase实时数据库中的数据结构:

enter image description here

2 个答案:

答案 0 :(得分:1)

snapshot.value返回一个Map,并且您正在使用List来存储它。也许这里最简单的解决方案是使用var类型来声明您的map变量:

var map = snapshot.value;

,但是最好在变量中设置类型。因此,在这种情况下,最好的选择是这样设置:

Map<dynamic, dynamic> map = snapshot.value;

查看dart文档,以提高您使用地图和列表的技巧以及它们的工作方式Lists docs Maps docs

答案 1 :(得分:1)

因为错误消息显示snapshot.value不是List,而是一个映射,所以行 List map = snapshot.value; 将始终失败。由于您正在从数据库中读取“公司”节点树,因此这将返回一个地图地图,类似于Map<String, Map<dynamic,dynamic>>,其中包含来自相应节点的所有数据。我将为您提供一个分析Company对象中的Json数据的函数,并在源代码中留下一些注释以尝试向您解释该过程。很简单。

List<Company> _parseData(DataSnapshot dataSnapshot) {
    List<Company> companyList =new List();

    // here you replace List map = snapshot.value with...
    Map<String, dynamic> mapOfMaps = Map.from( dataSnapshot.value );
    //actually dynamic here is another Map, String are the keys like -LXuQmyuF7E... or LXuSkMdJX... 
   //of your picture example and dynamic other Map    

    //in next lines we will interate in all values of your map
    //remeber that the values are maps too, values has one map for each company. 
    //The values are Map<String, dynamic>
    //in this case String are keys like category, company_name, country, etc... 
    //and dynamics data like string, int, float, etc

    //parsing and adding each Company object to list
    mapOfMaps.values.forEach( (value) {
      companyList.add(
          //here you'll not use fromSnapshot to parse data,
          //i thing you got why we're not using fromSnapshot
          Company.fromJson( Map.from(value) )
      );
    });

    return companyList;

  }

请注意,当您从以下位置读取特定公司时,将使用Company.fromSnapshot(snapshot)   您的数据库,类似...

// just to illustrate
var snapshot = await FirebaseDatabase.instance
      .reference()
      .child("Companies")
      .child(companyId).once();
Company.fromSnapshot( snapshot );

因为在这种情况下,snapshot.value是单个映射。 好吧,另一件事是,在您的statefull小部件中查看您的initState方法,我不知道这是否是一个好方法。 即使在执行Future之后,方法也会在initState方法内调用setState。这只是一个建议。