3
votes

So, I'm building my app in Flutter and unfortunately, I have recently come across an error. So what I want to do in my TestProvider class is to get data from firestore (what getQuestionFromFirebase() function is doing), and after that happens, I want to create a map from DocumentSnapshot (what questionMapFromFirebase() function is doing). And there comes an error, because I can't async in map function so my function doesn't wait for the result from previous function, and returns null. Any solutions? *I tried to return map from getQuestionFromFirebase() - Future, but later I can't use value from it because, my function wants pure map.

 class TestProvider {
  FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future<DocumentSnapshot> getQuestionFromFirebase(String documentId) async {
    return await _firestore.collection('questions').doc(documentId).get();
  }

  Map questionMapFromFirebase(String documentId) {
    Map questionMapFromFirebase;
    getQuestionFromFirebase(documentId).then((DocumentSnapshot carSnapshot) => {
          questionMapFromFirebase = carSnapshot.data(),
        });
    return questionMapFromFirebase;
  }
}

Later I'm using this function there: I'm using this function later there

List<Question> listOfQuestions() {
    List<int> range = numberInRange(amountOfQuestions);
    List<Question> listOfQuestions;
    for (int i = 1; i <= amountOfQuestions; i++) {
      listOfQuestions.add(Question.fromMap(
          _testProvider.questionMapFromFirebase(range[1].toString())));
    }
    return listOfQuestions;
  }

And that's creating error when Future occurs.

 The argument type 'Future<Map<dynamic, dynamic>>' can't be assigned to the parameter type 'Map<String, dynamic>'.

Edit: So recently I've made some changes to my code and now it looks like that

class TestProvider {
  FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future<DocumentSnapshot> getQuestionFromFirebase(String documentId) async {
    return await _firestore.collection('questions').doc(documentId).get();
  }

  Future<Map> questionMapFromFirebase(String documentId) async {
    DocumentSnapshot ds = await getQuestionFromFirebase(documentId);
    return ds.data();
  }
}

and repository

class TestRepository {
  final int amountOfQuestions;
  TestRepository({
    @required this.amountOfQuestions,
  });

  TestProvider _testProvider;

  Future listOfQuestions() async {
   List<int> range = numberInRange(amountOfQuestions);
   List<Question> listOfQuestions;
   for (int i = 1; i <= amountOfQuestions; i++) {
    listOfQuestions.add(Question.fromMap(
      await _testProvider.questionMapFromFirebase(range[i].toString())));
   }
  return listOfQuestions;
  }
}

The problem I started to see that is that every time i tried to call function questionMapFromFirebase from TestProvider, it has been working just fine. But when i tried to call it from TestRepository it throw the error:

E/flutter (13348): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'questionMapFromFirebase' was called on null.
E/flutter (13348): Receiver: null
E/flutter (13348): Tried calling: questionMapFromFirebase("2")

Any other sugestions how can I handle it?

1

1 Answers

2
votes
Future<Map> questionMapFromFirebase(String documentId) async {
   DocumentSnapshot ds = await getQuestionFromFirebase(documentId);
   return ds.data();
  }

Edit check FutureBuilder class

example, it will be inside your widget tree where the list need to be shown.

return FutureBuilder(
  future: _loadQuestions(),
  builder: (context, snapshot) {
    if(snapshot.connectionState == ConnectionState.done){
      return widgetForListing(snapshot.data);
    }
    return Center(child: Text('Loading...'));
  },
);

And your _loadQuestions function will be as

_loadQuestions() async {
    List<int> range = numberInRange(amountOfQuestions);
    List<Question> listOfQuestions = [];
    for (int i = 1; i <= amountOfQuestions; i++) {
        listOfQuestions.add(Question.fromMap(
      await _testProvider.questionMapFromFirebase(range[1].toString())));
    }
    return listOfQuestions; //you can get this list in **snapshot.data** of future builder
}