flutter - 将 Firestore DocumentSnapshot 转换为 Flutter 中的 map

标签 flutter google-cloud-firestore

我需要使用 Flutter 在 Firestore 中更新包含嵌套数组的文档。

所以我需要将完整的文档放入一个 map 中,对“sections”数组中的 map 重新排序,然后将数据存储回文档中。

但是我不熟悉如何将快照 (DocumentSnapshot) 的数据放入 map 中。

下面是一个我尝试实现的不起作用的示例:

final Map<String, dynamic> doc = snapshot.data as Map<String, dynamic>;

“snapshot.data”包含文档的值。文档的结构如下所示:

{
  name: "Course 1"
  sections: [
    {name: "Section 1"},
    {name: "Section 2"}
  ]
}

重新排序 sections 数组中的 map 后,我需要将数据保存回文档中。

  • 问题 1:如何将 snapshot.data 的内容读取到 Map 中?
  • 问题 2:我会删除文档,然后重新添加吗?或者我可以只更新所有内容吗?

这里是完整的功能。相关代码在“onDragFinish”中。

 // Build editable list with draggable list tiles and swipe to delete
  List<Widget> buildListViewEdit() {
    final course = db.collection("school").document("3kRHuyk20UggHwm4wrUI")
      .collection("course").document("74UsE9x7Bsgnjz8zKozv").snapshots();

    return [
      StreamBuilder(
        stream: course,
        builder: (context, snapshot) {
          if (!snapshot.hasData) return const Text("Loading...");

          return Expanded(
            child: DragAndDropList(
              snapshot.data["sections"].length,
              itemBuilder: (context, index) {
                return Card(
                  child: ListTile(
                    title: Text(snapshot.data["sections"][index]["name"]),
                    onTap: () {
                      print("hello");
                    }                    
                  )
                );
              },
              onDragFinish: (before, after) {
                print('on drag finish $before $after');

                //final docString = snapshot.data.toString();

                final Map <String, dynamic> doc = snapshot.data;

                //final tempSections = List.castFrom(snapshot.data["sections"]).toList();

                //Map data = tempSections[before];

                //tempSections.removeAt(before);
                //tempSections.insert(after,data);

                //snapshot.data["sections"] = tempSections;

                //db.collection("school").document("3kRHuyk20UggHwm4wrUI")
                  //.collection("course").document("74UsE9x7Bsgnjz8zKozv").updateData(snapshot.data);

                //var line = snapshot.data["sections"][before];

                //snapshot.data["sections"].removeAt(before);
                //snapshot.data["sections"].insert(after,line);

                /*
                List<Map> sections = docCopy["sections"];

                Map data = docCopy["sections"][before];
                sections.removeAt(before);
                sections.insert(after, data);
                print(sections);   
                */         
              },
              canDrag: (index) {
                print('can drag $index');
                return index != 3;
              },
              canBeDraggedTo: (one, two) => true,
              dragElevation: 8.0,
            )
          );
        }
      )
    ];   
  }

尝试将 snapshot.data 复制到另一个变量时出错:

flutter: ══╡ EXCEPTION CAUGHT BY GESTURE LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown while routing a pointer event:
flutter: type 'DocumentSnapshot' is not a subtype of type 'Map<String, dynamic>'
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter:   https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      _SectionScreenState.buildListViewEdit.<anonymous closure>.<anonymous closure> (package:teach_mob/screens/section_screen.dart:150:45)

工作示例

感谢大家的帮助。这是一个对我有用的完整示例:

  // Build editable list with draggable list tiles and swipe to delete
  List<Widget> buildListViewEdit() {
    final course = db.collection("school").document("3kRHuyk20UggHwm4wrUI")
      .collection("course").document("74UsE9x7Bsgnjz8zKozv").snapshots();

    return [
      StreamBuilder(
        stream: course,
        builder: (context, snapshot) {
          if (!snapshot.hasData) return const Text("Loading...");

          return Expanded(
            child: DragAndDropList(
              snapshot.data["sections"].length,
              itemBuilder: (context, index) {
                return Card(
                  child: ListTile(
                    title: Text(snapshot.data["sections"][index]["name"]),
                    onTap: () {
                      print("hello");
                    }                    
                  )
                );
              },
              onDragFinish: (before, after) {
                print('on drag finish $before $after');

                // Convert AsyncSnapshot to DocumentSnapshot and then
                // create a map that can be changed and updated.
                final Map <String, dynamic> doc = snapshot.data.data;

                // Convert fixed length list to dynamic list, because items in
                // fixed length lists can't be added / removed.
                final tempSections = List.castFrom(doc["sections"]).toList();

                // Get the data of the list item to be dragged
                // Remove the data from the current position
                // Add the data to the new position of the list
                Map data = tempSections[before];

                tempSections.removeAt(before);
                tempSections.insert(after,data);

                // Overwrite sections with new list array
                doc["sections"] = tempSections;

                // Store the data back into the firestore document
                db.collection("school")
                  .document("3kRHuyk20UggHwm4wrUI")
                  .collection("course")
                  .document("74UsE9x7Bsgnjz8zKozv")
                  .updateData(doc);
              },
              canDrag: (index) {
                print('can drag $index');
                return index != 3;
              },
              canBeDraggedTo: (one, two) => true,
              dragElevation: 8.0,
            )
          );
        }
      )
    ];   
  }

最佳答案

根据我们的讨论,快照不是 DocumentSnapshot 它是 AsyncSnapshot

获取 DocumentSnaphot 使用 snapshot.data

要获取实际 map ,您可以使用 snapshot.data.data()

这将返回您要查找的 Map

关于flutter - 将 Firestore DocumentSnapshot 转换为 Flutter 中的 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56721694/

相关文章:

flutter - 从Flutter中的Firestore检索数据后为空列表

flutter - 如何将参数从一个选项卡传递到另一个选项卡?

list - Dart 的 List 的 "some"方法叫什么?检查是否至少有一个元素通过测试的方法

firebase - 如何在 Flutter 中用 Column 或 ListView 类包装 StreamBuilder 类?

javascript - Firebase:使用 JavaScript SDK 加入 Firestore 文档结果

Javascript 函数乱序完成——异步

android - Flutter - 多选 ListView

Dart 不变性

android - 如何使用云功能向具有 FCM token 的多个设备发送推送通知

typescript - Firebase 类型和默认 tslint.json 的非隐式依赖