Flutter/Firestore returns type List<Review> is not a subtype of type 'Map<String, dynamic>' when retrieving snapshots from Stream

Viewed 82

I am trying to retrieve a collection with it's sub-collection using firestore realtime database and displaying the results in ListViewbut instead I got type List<Review> is not a subtype of type 'Map<String, dynamic>' and I couldn't get around it.

Question What should I change in order for this to return the needed results properly?

This is reviews_service.dart:

class ReviewsService {
  var currentUser = FirebaseAuth.instance.currentUser;
  var firestoreInstance = FirebaseFirestore.instance;

  Stream<List<T>> reviewsCollectionStream<T>({
    @required String path,
    @required T builder(Map<String, dynamic> data),
  }) {
    final reference = firestoreInstance.collection(path);
    final snapshots = reference.snapshots();
    return snapshots.map((snapshot) =>
        snapshot.docs.map((snapshot) => builder(snapshot.data())).toList());
}

Those are my model classes review.dart and client.dart

class Review {
  final String reviewTitle;
  final String reviewContent;
  final Client owner;

  Review(
    {this.reviewTitle,
    this.reviewContent,
    this.owner});

  factory Review.fromMap(Map<String, dynamic> map) {
    if (map == null) return null;

    return Review(
      reviewTitle: map['revieewTitle'],
      reviewContent: map['reviewContent'],
      owner: Client.fromMap(map['owner']),
    );
  }
}

class Client {
  final String clientUID;
  final String clientEmail;
  final String clientName;

  Client({this.clientUID, this.clientEmail, this.clientName});

  factory Client.fromMap(Map<String, dynamic> map) {
    if (map == null) return null;

    return EndUser(
      clientUID: map['clientId'],
      clientEmail: map['clientEmail'],
      clientDisplayName: map['clientName'],
    );
  }
}

Here's where I retrieve the data and display them in the Listview reviews_page.dart:

class _ReviewsPageState extends State<ReviewsPage> {
  final reviews = _mReviewService.reviewssCollectionStream(path: "reviews", builder: (data) => Review.fromMap(data));
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        child: StreamBuilder<Object>(
           stream: reviews,
           builder: (context, snapshot) {
              if (snapshot.hasData) {
                return ListView.builder(
                  controller: _scrollController,
                  itemBuilder: (BuildContext context, int index) {
                    Review rev = new Review(
                        reviewTitle: (snapshot.data as Map)["reviewTitle"][index].toString(),
                        reviewContent: (snapshot.data as Map)["reviewContent"][index].toString(),                      
                        owner: (snapshot.data as Map)["reviewOwner"][index]);
                    return Review(review: rev,);
                  },
               );
              } else {return Center(child: Text('there are no reviews'));}
            }),
      ),
    );
  }
}

UPDATE I got working the retrieving is running properly my only problem now is that the Client subcollection is null! is there anything wrong with Stream<List<T>> reviewsCollectionStream<T>({...}) ?

This is what I did: in reviews_page.dart and inside itemBuilder:

instead of

Review rev = new Review(
                reviewTitle: (snapshot.data as Map)["reviewTitle"][index].toString(),
                reviewContent: (snapshot.data as Map)["reviewContent"][index].toString(),                      
                owner: (snapshot.data as Map)["reviewOwner"][index]);

I recovered it as List:

//only one line that's all what it takes
Review rev = (snapshot.data as List)[index]; 

but I still cant retrieve the subcollection of clients

1 Answers

Firestore Snapshots don't include subcollections

If you want subcollection data, you'll have to make new query using the subcollection name that you know ahead of time

Also, see this link for reference on how to get subcollection data

Related