Home > Software engineering >  Flutter How to make a pagination from streambuilder with firestore (lazy loading)
Flutter How to make a pagination from streambuilder with firestore (lazy loading)

Time:06-04

Hello please I am new in flutter mobile devellopement. I would like to do a pagination (Lazy loading from streambuilder with firestore). Indeed when I do a stream all the documents load and it takes a long time and also my application sometimes bugs (maybe because I loaded a lot of data in memory). I would like to simplify things by using a pagination but I don't really know how to do it. or you can load 10 documents per call. please help me find a solution to avoid bugging my application and load less document per call. here is the full code of the feed part

class FeedJob extends StatefulWidget {
  FeedJob({Key? key}) : super(key: key);

  @override
  _FeedJobState createState() => _FeedJobState();
}

class _FeedJobState extends State<FeedJob> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: StreamBuilder<QuerySnapshot>(
            stream: FirebaseFirestore.instance
                .collection("job_feed")
                .orderBy("time", descending: true)
                .snapshots(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else {
                return Column(
                  children: [
                    Expanded(
                        flex: 0,
                        child: Column(children: [
                          TiTle(title: "Feeds"),
                        ])),
                    Expanded(
                      child: ListView(
                        children: [
                          ListView(
                              shrinkWrap: true,
                              physics: NeverScrollableScrollPhysics(),
                              children: snapshot.data!.docs.map((e) {
                                return Column(
                                  children: [
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Card(
                                        child: Column(
                                          children: [
                                            ListTile(
                                              leading: Container(
                                                width: 40,
                                                height: 40,
                                                alignment: Alignment.topCenter,
                                                decoration: BoxDecoration(
                                                    image: DecorationImage(
                                                        alignment:
                                                            Alignment.topCenter,
                                                        fit: BoxFit.cover,
                                                        image:
                                                            CachedNetworkImageProvider(
                                                                e.get(
                                                                    'photo'))),
                                                    color: Colors.blue
                                                        .withOpacity(.2),
                                                    borderRadius:
                                                        BorderRadius.all(
                                                            Radius.circular(
                                                                20))),
                                              ),
                                              trailing: Column(
                                                children: [
                                                  Icon(Icons.comment_rounded,
                                                      size: 15,
                                                      color: Colors.grey),
                                                  Text("comment".tr,
                                                      style: TextStyle(
                                                          fontSize: 8,
                                                          color: Colors.grey))
                                                ],
                                              ),
                                              title: Text(e.get('name'),
                                                  style: TextStyle(
                                                      color: Colors.black,
                                                      fontSize: 10,
                                                      fontWeight:
                                                          FontWeight.bold)),
                                              subtitle:
                                                  Text(e.get('time').toString(),
                                                      style: TextStyle(
                                                        fontSize: 8,
                                                        color: Colors.grey,
                                                      )),
                                            ),
                                            Padding(
                                              padding: const EdgeInsets.only(
                                                  left: 5.0,
                                                  right: 8,
                                                  bottom: 15),
                                              child: Text(
                                                e.get('description'),
                                                textAlign: TextAlign.justify,
                                              ),
                                            )
                                          ],
                                        ),
                                      ),
                                    )
                                  ],
                                );
                              }).toList()),
                        ],
                      ),
                    ),
                  ],
                );
              }
            }));
  }
}

CodePudding user response:

You can use startAfterDocument to tell Firestore what was the last document you fetched (assuming you keep a reference to it each time).

// Prepare the query.
final List<JobModel> fetchedData = [];
final int firstBatchSize = 6;
final int nextBatchSize = 12;

DocumentSnapshot<JobModel>? lastDocument;

final Query<DestinationModel> query = FirebaseFirestore.instance  
  .collection('jobs')
  .orderBy('time', descending: true)
  .withConverter<JobModel>(
    fromFirestore: (snapshot, _) =>  JobModel.fromFirestore(snapshot),
    toFirestore: (JobModel job, _) => job.toFirestore(),
  );

// Set the starting point of the query.
if (lastDocument != null) query.startAfterDocument(lastDocument);

// Set the limit for the query.
query.limit(fetchedData.isEmpty ? firstBatchSize : nextBatchSize);

// Run the query.
final QuerySnapshot<JobModel> results = await query.get();

// Do something with the results; Store the last document fetched.
  • Related