Tim B.
Tim B.

Reputation: 88

Flutter Asynchronous firebase request not awaited

I am starting my first Firebase project with flutter and want to retrieve data from my Firebase CloudFirestore database and display it in the application.

I am getting the data from Firebase with this class:

class getFirebaseData
{
  List<ArticleItems> requestedItems = [];

  Future<List<ArticleItems>> getFirebaseArticles()
  {

    //Create new Firebase instance
    final firestoreInstance = FirebaseFirestore.instance;

    //Get data from Firebase
    firestoreInstance.collection("categories/politik/articles").snapshots().listen((data) =>
    //For each found document run loop
      data.docs.forEach((doc) {

        //Convert Firebase timestamp to DateTime
        Timestamp firebaseTimestamp = doc.data()['articlePublishTimestamp'];
        DateTime firebaseDateTime = DateTime.fromMicrosecondsSinceEpoch(firebaseTimestamp.microsecondsSinceEpoch);

        //Create new ArticleItem and insert data from Firebase
        ArticleItems firebaseItem = new ArticleItems(
            article_id: doc.data()['articleId'],
            article_thumbnail_url: doc.data()['articleThumbnailUrl'],
            article_headline: doc.data()['articleHeadline'],
            article_fulltext: doc.data()['articleFulltext'],
            article_author: doc.data()['articleAuthor'],
            article_category: doc.data()['articleCategory'],
            article_publish_timestamp: firebaseDateTime
        );

        //Add created item to list of all requested items
        requestedItems.add(firebaseItem);

        print('Future finished');
      }));

    }
}

In my main method I am trying to await the result of the request and want to output it (tried to get only the length first to check if there are entries in the list). I used this code for that:

  //Async request to get Firebase Data
  void getArticleInformation() async
  {
    getFirebaseData firebaseData = getFirebaseData();
    await firebaseData.getFirebaseArticles();

    print('Await finished');

    articleItems = firebaseData.requestedItems;
    print("Length FirebaseItems: " + firebaseData.requestedItems.length.toString());
    print("Length ArticleItems: " + articleItems.length.toString());
  }

When I am running the application the length of the returned list is zero (should be 2) and the console output "Await finished" appears before the output "Future finished". To me it seems like the await function is not waiting for the result and just starting to progress the next lines of code.

It would be great if you can show me what I did wrong there and how to fix it.

Upvotes: 0

Views: 206

Answers (1)

Karl Wolf
Karl Wolf

Reputation: 363

(I did not test this code.. if somethings wrong or not working tell me :)

You could try somethong like this, looks much cleaner:

class FirebaseRepository {
  Future<List<ArticleItems>> getArticleItems() {
    var instance = Firestore.instance();
    var snapshot = await instance.collection("categories/politik/articles").get();
    return snapshot.docs.map((e)=>ArticleItem.fromSnapshot(e)).toList();
  }

}

And in your ArticleItem like this:

class ArticleItem {

  factory ArticleItem.fromSnapshot(QueryDocumentSnapshot snapshot) {
    return ArticleItem(
      article_id: snapshot.get("articleId"),
      article_thumbnail_url: snapshot.get("articleThumbnailUrl"),
      article_headline: snapshot.get("articleHeadline"),
      article_fulltext: snapshot.get("articleFulltext"),
      article_author: snapshot.get("articleAuthor"),
      article_category: snapshot.get("articleCategory"),
      article_publish_timestamp: firebaseDateTime
    );
  }
}

Retrieve the items like this:

articleItems = await new FirebaseRepository().getArticleItems();

Upvotes: 1

Related Questions