在Flutter中将Firestore文档快照转换为Map

6qfn3psc  于 2022-12-14  发布在  Flutter
关注(0)|答案(8)|浏览(223)

我需要在Firestore with Flutter中更新一个包含嵌套数组的文档。
因此,我需要将整个文档放入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:如何将www.example.com的内容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,
            )
          );
        }
      )
    ];   
  }

尝试将www.example.com复制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,
            )
          );
        }
      )
    ];   
  }
imzjd6km

imzjd6km1#

根据我们的讨论,快照不是DocumentSnapshot,而是AsyncSnapshot
要获取文档快照,请使用snapshot.data
要获得实际的Map,可以使用snapshot.data.data()
它将返回您要查找的Map〈String,dynamic〉。

sf6xfgos

sf6xfgos2#

2021年5月更新

请参阅移转至cloud_firestore 2.0.0 here

//Replace this:
- StreamBuilder<DocumentSnapshot>(
//With this:
+ StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(

创建变量时必须定义类型:

Future<void> example(
    -  DocumentReference documentReference,
    +  DocumentReference<Map<String, dynamic>> documentReference,
    -  CollectionReference collectionReference,
    +  CollectionReference<Map<String, dynamic>> collectionReference,
    -  Query query,
    +  Query<Map<String, dynamic>> query,
) {
2vuwiymt

2vuwiymt3#

为了示例

需要简化

class ItemsList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // get the course document using a stream
    Stream<DocumentSnapshot> courseDocStream = Firestore.instance
        .collection('Test')
        .document('4b1Pzw9MEGVxtnAO8g4w')
        .snapshots();

    return StreamBuilder<DocumentSnapshot>(
        stream: courseDocStream,
        builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {

            // get course document
            var courseDocument = snapshot.data.data;

            // get sections from the document
            var sections = courseDocument['sections'];

            // build list using names from sections
            return ListView.builder(
              itemCount: sections != null ? sections.length : 0,
              itemBuilder: (_, int index) {
                print(sections[index]['name']);
                return ListTile(title: Text(sections[index]['name']));
              },
            );
          } else {
            return Container();
          }
        });
  }
}

结果

bihw5rsg

bihw5rsg4#

看起来可能是因为你有一个流构建器,所以快照是一个**AsyncSnapshot<dynamic>,当你获取它的.data时,你会得到一个动态**,它会返回一个DocumentSnapshot,* 然后你需要调用这个对象 * 上的.data来获取正确的**Map<String, dynamic> data**。

builder: (context, snapshot) {
final DocumentSnapshot  ds = snapshot.data;
final Map<String, dynamic> map = ds.data;
}

第一次
你也可以使用内置函数追加到数组中,但是看起来你想做一些疯狂的排序,所以一切都很好。

kulphzqa

kulphzqa5#

2020年9月更新

要从快照文档中获取数据,现在必须调用snapshot.data()(cloud_firestore 0.14.0 or higher

gk7wooem

gk7wooem6#

要从文档快照获取**Map,**请使用snapshot.data.data

umuewwlo

umuewwlo7#

我认为你们都错了。
从Firestore数据库获取Map字段的唯一方法是使用代码docs.get("MapVariableName") as Map<String, dynamic>,如下面的示例代码所示:

Widget userFstore(BuildContext context, DocumentSnapshot docs, int index) {
    //Assign it into new Map using variable late Map
    late Map<String, dynamic> userInfo = docs["user"] as Map<String, dynamic>;
    //Then access its key like this method below
    late String name = userInfo["name"] as String;
    late String imgURL = userInfo["imgURL"] as String;
    late String imgName = userInfo["imgName"] as String;
    late String desc = userInfo["desc"] as String;
    late String email = userInfo["email"] as String;
    late bool active = userInfo["active"] as bool;
    
    return const SizedBox();
 }
smdncfj3

smdncfj38#

根据以上答案,您可以尝试以下方法

Position p = snapshot.data as Position;

相关问题