首页 > 解决方案 > 如何在 Flutter 项目中显示来自 Firebase 的 QueryDocumentSnapshot?(颤振,Firebase,Json,飞镖)

问题描述

以下是一个名为“week”的示例 QueryDocumentSnapshot,我使用 StreamBuilder 从 Firestore 获得。我正在寻找一种方法来显示这些或多或少复杂的数据,例如 Card-Widget,其中包含来自 Flutter 项目中每个快照的信息。

{
    "days":{
        "3": {
            "activities": {
                "1628658343103": {
                    "query": "I am watering the plants", 
                    "finished": false, 
                    "params": [
                        {
                            "pronounsDefinite": "I"
                        }, 
                        {
                            "verbsHelpPresent": "am"
                        },
                        {
                            "verbsGerund": "watering"
                        }, 
                        {
                            "articles": "the"
                        }, 
                        {
                            "nouns": "plant"
                        }
                    ], 
                    "intent": "gHomesAndBuildingsGardensAC", 
                    "duration": 3
                }, 
                "1628673512954": {
                    "query": "I am cutting the bushes", 
                    "finished": false, 
                    "params": [
                        {
                            "pronounsDefinite": "I"
                        }, 
                        {
                            "verbsHelpPresent": "am"
                        }, 
                        {
                            "verbsGerund": "cutting"
                        }, 
                        {
                            "articles": "the"
                        }, 
                        {
                            "nouns": "bush"
                        }
                    ], 
                    "intent": "gHomesAndBuildingsGardensAC", 
                    "duration": 3
                }, 
                "1628673476549": {
                    "query": "I work in the garden", 
                    "finished": false, 
                    "params": [
                        {
                            "pronounsDefinite": "I"
                        }, 
                        {
                            "verbsInfinitiv": "work"
                        }, 
                        {
                            "prepositions": "in"
                        }, 
                        {
                            "articles": "the"
                        }, 
                        {
                            "nouns": "garden"
                        }], 
                    "intent": "gHomesAndBuildingsGardensAC", 
                    "duration": 4
                }
            }
        },
        "4": {
            "activities": {
                "1628658343104": {
                    "query": "I am watering the plants", 
                    "finished": false, 
                    "params": [
                        {
                            "pronounsDefinite": "I"
                        }, 
                        {
                            "verbsHelpPresent": "am"
                        },
                        {
                            "verbsGerund": "watering"
                        }, 
                        {
                            "articles": "the"
                        }, 
                        {
                            "nouns": "plant"
                        }
                    ], 
                    "intent": "gHomesAndBuildingsGardensAC", 
                    "duration": 3
                }, 
                "1628673512956": {
                    "query": "I am cutting the bushes", 
                    "finished": false, 
                    "params": [
                        {
                            "pronounsDefinite": "I"
                        }, 
                        {
                            "verbsHelpPresent": "am"
                        }, 
                        {
                            "verbsGerund": "cutting"
                        }, 
                        {
                            "articles": "the"
                        }, 
                        {
                            "nouns": "bush"
                        }
                    ], 
                    "intent": "gHomesAndBuildingsGardensAC", 
                    "duration": 3
                }, 
                "1628673476559": {
                    "query": "I work in the garden", 
                    "finished": false, 
                    "params": [
                        {
                            "pronounsDefinite": "I"
                        }, 
                        {
                            "verbsInfinitiv": "work"
                        }, 
                        {
                            "prepositions": "in"
                        }, 
                        {
                            "articles": "the"
                        }, 
                        {
                            "nouns": "garden"
                        }], 
                    "intent": "gHomesAndBuildingsGardensAC", 
                    "duration": 3
                }
            }
        }
    }
}

这就是问题所在:我有一个 ListView.builder 方法,它为每个快照文档构建一个小部件,就像上面的那个一样。

“活动”中的数字键是时间戳。我可以使用这个显示一些文本:

...
Text(
  week['days']['3']['activities']['1628658343103']['query'].toString()
), //Which displays: "I am watering the plants"

但是这样我就必须知道每个时间戳,并用显然不起作用的确切数字这样称呼它。

如何使用“forEach()”之类的东西来遍历活动中的所有现有条目?

我还为此使用https://app.quicktype.io构建了一个模型类, 但随后它引发了 FormatException,因为我在尝试此操作时尝试将 QueryDocumentSnapshot 粘贴到该类:

Widget buildCard(BuildContext context, DocumentSnapshot week) {
    final dataFromWeek = dataFromWeekFromJson(week.toString());
    return new Container(.....); 

    //In this Container, all the text from json should be displayed
}

这是我从 JSON QuickType 工具获得的模型类。

// To parse this JSON data, do
//
//     final dataFromWeek = dataFromWeekFromJson(jsonString);

import 'dart:convert';

DataFromWeek dataFromWeekFromJson(String str) =>
    DataFromWeek.fromJson(json.decode(str));

String dataFromWeekToJson(DataFromWeek data) => json.encode(data.toJson());

class DataFromWeek {
  DataFromWeek({
    this.days,
  });

  Map<String, Day> days;

  factory DataFromWeek.fromJson(Map<String, dynamic> json) => DataFromWeek(
        days: Map.from(json["days"])
            .map((k, v) => MapEntry<String, Day>(k, Day.fromJson(v))),
      );

  Map<String, dynamic> toJson() => {
        "days": Map.from(days)
            .map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
      };
}

class Day {
  Day({
    this.activities,
  });

  Map<String, Activity> activities;

  factory Day.fromJson(Map<String, dynamic> json) => Day(
        activities: Map.from(json["activities"])
            .map((k, v) => MapEntry<String, Activity>(k, Activity.fromJson(v))),
      );

  Map<String, dynamic> toJson() => {
        "activities": Map.from(activities)
            .map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
      };
}

class Activity {
  Activity({
    this.query,
    this.finished,
    this.params,
    this.intent,
    this.duration,
  });

  String query;
  bool finished;
  List<Param> params;
  String intent;
  int duration;

  factory Activity.fromJson(Map<String, dynamic> json) => Activity(
        query: json["query"],
        finished: json["finished"],
        params: List<Param>.from(json["params"].map((x) => Param.fromJson(x))),
        intent: json["intent"],
        duration: json["duration"],
      );

  Map<String, dynamic> toJson() => {
        "query": query,
        "finished": finished,
        "params": List<dynamic>.from(params.map((x) => x.toJson())),
        "intent": intent,
        "duration": duration,
      };
}

class Param {
  Param({
    this.pronounsDefinite,
    this.verbsHelpPresent,
    this.verbsGerund,
    this.articles,
    this.nouns,
    this.verbsInfinitiv,
    this.prepositions,
  });

  String pronounsDefinite;
  String verbsHelpPresent;
  String verbsGerund;
  String articles;
  String nouns;
  String verbsInfinitiv;
  String prepositions;

  factory Param.fromJson(Map<String, dynamic> json) => Param(
        pronounsDefinite:
            json["pronounsDefinite"] == null ? null : json["pronounsDefinite"],
        verbsHelpPresent:
            json["verbsHelpPresent"] == null ? null : json["verbsHelpPresent"],
        verbsGerund: json["verbsGerund"] == null ? null : json["verbsGerund"],
        articles: json["articles"] == null ? null : json["articles"],
        nouns: json["nouns"] == null ? null : json["nouns"],
        verbsInfinitiv:
            json["verbsInfinitiv"] == null ? null : json["verbsInfinitiv"],
        prepositions:
            json["prepositions"] == null ? null : json["prepositions"],
      );

  Map<String, dynamic> toJson() => {
        "pronounsDefinite": pronounsDefinite == null ? null : pronounsDefinite,
        "verbsHelpPresent": verbsHelpPresent == null ? null : verbsHelpPresent,
        "verbsGerund": verbsGerund == null ? null : verbsGerund,
        "articles": articles == null ? null : articles,
        "nouns": nouns == null ? null : nouns,
        "verbsInfinitiv": verbsInfinitiv == null ? null : verbsInfinitiv,
        "prepositions": prepositions == null ? null : prepositions,
      };
}

我实际上并不想显示“参数”,但如果有一些灵活性会很棒,这就是为什么我尝试使用模型类在“卡片小部件”中显示快照数据的原因。

标签: jsonfirebaseflutterdart

解决方案


您想要获取特定日期的所有活动,然后循环浏览它并创建一张卡片。

首先,这是您应该如何构建数据的方式。

'days'(集合)-> '3'(文档)-> 'activities'(文档 3 下的子集合)

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: StreamBuilder<QuerySnapshot<Activity>>(
      // below will return all the activities for under doc('3')
      stream: FirebaseFirestore.instance
          .collection("days")
          .doc('3')
          .collection("activities")
          // NB: I used your Activity Model
          .withConverter<Activity>(
            fromFirestore: (snapshot, _) =>
                Activity.fromJson(snapshot.data()),
            toFirestore: (data, _) => data.toJson(),
          )
          .snapshots(),
      builder: (BuildContext context,
          AsyncSnapshot<QuerySnapshot<Activity>> snapshot) {
        if (snapshot.hasError) return Text('Something went wrong');
        if (snapshot.connectionState == ConnectionState.waiting)
          return CircularProgressIndicator();

        // you can then loop through query and build the card;
        List<Activity> _activities =
            snapshot.data.docs.map((e) => e.data()).toList();
        return ListView.builder(
          itemCount: _activities.length,
          itemBuilder: (context, i) {
            // you can return a card here.
            return ListTile(
              title: Text(_activities[i].query),
            );
          },
        );
      },
    ),
  );
}

推荐阅读