Patrick Schick
Patrick Schick

Reputation: 393

Null List after data retrieval from Firestore in Flutter

I am new at Flutter so I am sorry if this problem seems trivial or irrelevant!

I have created another class for getting and setting data, Repository, as I use Cloud Firestore, the data I want for this specific question is stored in a collection, so I get all the documents in the collection as a QuerySnapshot and then add all the documents in a List<DocumentSnapshot>.

Here is the method:

Future<List<DocumentSnapshot>> getCollection(CollectionReference colRef) async {
    List<DocumentSnapshot> dummyList = new List();
    await colRef.getDocuments().then((value) {
      dummyList.addAll(value.documents);
    });
    return dummyList;
  }

Repository:

CollectionReference memoriesColRef =
    _firestore
        .collection("username")
        .document("memories")
        .collection("allMem");

    List<DocumentSnapshot> documentList = new List();
    await getCollection(memoriesColRef).then((value) {
      documentList.addAll(value);
    });

After all this, I have set up a method in my UI class, to call this Repository, and it works perfectly there bet when I call it in the build function, the global list I have passed to access the data, is not able to add the values in it

UI Class

build(...) {
  getMemories().then((value) {
      print("value size: " + value.length.toString()); // 1
      memoriesListMap.addAll(value); // global variable
    });
  print("valSize: " + memoriesListMap.length.toString()); // 0
  print("val: " + memoriesListMap[0]["title"]); // error line
}

Future<List<Map<String, dynamic>>> getMemories() async{
    List<Map<String, dynamic>> dummyListMap = new List();

    await MemoryOper().getMemories().then((value) {
      print("memVal: " + value[0]["title"]); // appropriate value
      dummyListMap.addAll(value);
    });
    return dummyListMap;
  }

ERROR RangeError (index): Invalid value: Valid value range is empty: 0\

I don't know what's causing this, but please help me out! Thank you

EDIT:

ListView.builder(
                itemBuilder: (BuildContext context, int index) {
                  String title = memoriesListMap[index]["title"]; // error prone line
                  int remind = memoriesListMap[index]["remind"];
                  String link = memoriesListMap[index]["link"];

Upvotes: 0

Views: 162

Answers (2)

Emmanuel
Emmanuel

Reputation: 1494

I addition to what nvoigt has said, This article will help you to understand how to implement the Future Builder, in your specific case you can do something like:

build(...){
..
body: getMemories(),
..
}

Widget getMemories() {
  return FutureBuilder(
    builder: (context, projectSnap) {
      if (projectSnap.connectionState == ConnectionState.none &&
          projectSnap.hasData == null) {
        return Container();
      }
      return ListView.builder(
        itemCount: projectSnap.data.length,
        itemBuilder: (context, index) {
          ProjectModel project = projectSnap.data[index];
          return Column(
            children: <Widget>[
              // Widget to display the list of project
            ],
          );
        },
      );
    },
    future: getCollection(), //this is the important part where you get the data from your Future
  );
}

Upvotes: 1

Shri Hari L
Shri Hari L

Reputation: 4894

I think you are accessing the element before it gets added since it is async method.
Try something like this,

build(...) {
  getMemories().then((value) {
      print("value size: " + value.length.toString()); // 1
      memoriesListMap.addAll(value); // global variable
      print("valSize: " + memoriesListMap.length.toString()); // 0
      print("val: " + memoriesListMap[0]["title"]); 
   });
}

Hope it works!

Upvotes: 0

Related Questions