Metronom
Metronom

Reputation: 258

Flutter Retrieving firestore collection using Stream

I am trying to retrieve a whole collection in firestore using StreamBuilder but I got stuck in mapping the result according to my dart model

This is the dart model thread.dart:

class Thread {
  final String threadTitle;
  final String threadContent;
  final String threadFlair;
  final String threadTimestamp;
  final List<String> threadLikedBy;
  final List<String> originalPoster;

  Thread({
    this.threadTitle,
    this.threadContent,
    this.threadTimestamp,
    this.threadFlair,
    this.threadLikedBy,
    this.originalPoster,
  });

  factory Thread.fromMap(Map<String, dynamic> map) => Thread(
    threadTitle: map["threadTitle"],
    threadContent: map["threadContent"],
    threadFlair: map["threadFlair"],
    threadTimestamp: map["threadTimestamp"],
    threadLikedBy: List<String>.from(map["threadLikedBy"].map((x) => x)),
    originalPoster: List<String>.from(map["originalPoster"].map((x) => x)),
  );

  Map<String, dynamic> toMap() => {
    "threadTitle": threadTitle,
    "threadContent": threadContent,
    "threadFlair": threadFlair,
    "threadTimestamp": threadTimestamp,
    "threadLikedBy": List<dynamic>.from(threadLikedBy.map((x) => x)),
    "originalPoster": List<dynamic>.from(originalPoster.map((x) => x)),
  };
}

This is the widget where I display the results in a listview:

class _ThreadsBodyState extends State<ThreadsBody> {
  final threads = _mThreadService.retriveData(path: "posts", builder: (data) => Thread.fromMap(data));
  @override
  Widget build(BuildContext context) {
    return Container(
      child: StreamBuilder<Object>(
        stream: threads,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemBuilder: (BuildContext context, int index) {
                Thread thrd = (snapshot.data as List)[index];
                return ThreadCard(thread: thrd,);
              },
            );
           } else {return Text('no data');}
      }),
    );
  }
}

and here's posts_service.dart where I have the Stream function

//After restructuring my model and adding: 
//List<String> threadLikedBy; and List<String> originalPoster;
//this method works no more

Stream<List<T>> retrieveData<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());
}

It appears to be that I am messing up the mapping in the return but I can't exactly figure out how to fix it.

Upvotes: 1

Views: 782

Answers (1)

Thorvald
Thorvald

Reputation: 3563

in your 'posts_services.dart' add the following function:

Future<QuerySnapshot> fetchThreads() async {
    return await firestoreInstance.collection('posts').get();
}

Now in your widget where you build your ListView should look like this:

class _ThreadsBodyState extends State<ThreadsBody> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: FutureBuilder<QuerySnapshot>(
        future: youService.fetchThreads(),
        builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data.size, //to retrieve the size
              itemBuilder: (BuildContext context, int index) {
                Thread thrd = Thread.fromMap(snapshot.data.docs[index].data());
                return ThreadCard(thread: thrd,);
              },
            );
           } else {return Text('no data');}
      }),
    );
  }
}

Upvotes: 2

Related Questions