Flutter 如何使用 firestore(延迟加载)从 streambuilder 进行分页

Flutter How to make a pagination from streambuilder with firestore (lazy loading)

你好,我是 flutter 移动开发的新手。我想进行分页(使用 firestore 从 streambuilder 延迟加载)。事实上,当我做一个流时,所有的文档都会加载,这需要很长时间,而且我的应用程序有时会出现错误(可能是因为我在内存中加载了大量数据)。我想通过使用分页来简化事情,但我真的不知道该怎么做。或者您可以每次调用加载 10 个文档。请帮助我找到一个解决方案,以避免窃听我的应用程序并在每次调用时加载更少的文档。这是提要部分的完整代码

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()),
                        ],
                      ),
                    ),
                  ],
                );
              }
            }));
  }
}

您可以使用 startAfterDocument 告诉 Firestore 您获取的最后一个文档是什么(假设您每次都保留对它的引用)。

// 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.