Flutter:从 firestore 延迟加载数据

2023-11-22

注意:我已经看到了关于 ListView 的延迟加载的答案,但这些是针对自定义 API 的,而不是针对 firestore 数据库的!

我有一个书籍摘要应用程序,应用程序从我的Firebase/Firestore数据库,然后使用ListView.builder它被包裹在一个StreamBuilder.

现在,我想延迟获取数据,我的意思是当用户滚动列表时,所需的数据会被加载,而不是立即加载数据然后延迟显示。

//The Widget used to display data:

Widget feed() {
  return Container(
    width: deviceWidth,
    height: deviceHeight / 3,
    child: StreamBuilder(
        stream: Firestore.instance
            .collection('feedItem')
            .orderBy('feedId', descending: true)
            .snapshots(),

        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            int totalLength = snapshot.data.documents.length;
            return ListView.builder(
              scrollDirection: Axis.horizontal,
              itemCount: totalLength > 10 ? 10 : totalLength,
              itemBuilder: (BuildContext context, int index) {
                return Container(
                  width: deviceWidth / 2.5,
                  child: GestureDetector(
                    onTap: () {
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (BuildContext context) => FeedIntro(
                                  snapshot.data.documents[
                                      ((totalLength - 1) - index)]['feedId'])));
                    },
                    child: Card(
                        child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        Container(
                          // width: 150,
                          height: 150,
                          foregroundDecoration: BoxDecoration(
                              image: DecorationImage(
                                  image: NetworkImage(
                                    snapshot.data.documents[index]['feedImage'],
                                  ),
                                  fit: BoxFit.fill)),
                        ),
                        Center(
                            child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text(snapshot.data.documents[index]['title']),
                        )),
                      ],
                    )),
                  ),
                );
              },
            );
          } else if (snapshot.hasError) {
            return Center(child: Text('Sorry Something went wrong!'));
          } else {
            return Center(
              child: SizedBox(
                child: CircularProgressIndicator(),
                width: 50,
                height: 50,
              ),
            );
          }
        }),
  );
}

您的延迟加载的描述似乎与分页相符。这是一个使用 Firestore 进行分页的简单演示ListView.builder

此示例实现了 Firebase 官方文档中的片段Firestore 分页.

在此演示中,有两种方法可以将数据加载到视图上。

  • 刷新整个ListView using RefreshIndicator
  • 向下滚动到列表底部以加载下一个文档ListView. ScrollController用于确定用户是否已点击列表的底部。
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

import 'DocObj.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize Firebase
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  var scrollController = ScrollController();

  @override
  void initState() {
    super.initState();
    getDocuments();
    scrollController.addListener(() {
      if (scrollController.position.atEdge) {
        if (scrollController.position.pixels == 0)
          print('ListView scroll at top');
        else {
          print('ListView scroll at bottom');
          getDocumentsNext(); // Load next documents
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: listDocument.length != 0
            ? RefreshIndicator(
                child: ListView.builder(
                  physics: AlwaysScrollableScrollPhysics(),
                  controller: scrollController,
                  itemCount: listDocument.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text('${listDocument[index].documentName}'),
                    );
                  },
                ),
                onRefresh: getDocuments, // Refresh entire list
              )
            : CircularProgressIndicator(),
      ),
    );
  }

  List<DocObj> listDocument;
  QuerySnapshot collectionState;
  // Fetch first 15 documents
  Future<void> getDocuments() async {
    listDocument = List();
    var collection = FirebaseFirestore.instance
        .collection('sample_pagination')
        .orderBy("name")
        .limit(15);
    print('getDocuments');
    fetchDocuments(collection);
  }

  // Fetch next 5 documents starting from the last document fetched earlier
  Future<void> getDocumentsNext() async {
    // Get the last visible document
    var lastVisible = collectionState.docs[collectionState.docs.length-1];
    print('listDocument legnth: ${collectionState.size} last: $lastVisible');

    var collection = FirebaseFirestore.instance
        .collection('sample_pagination')
        .orderBy("name").startAfterDocument(lastVisible).limit(5);

    fetchDocuments(collection);
  }

  fetchDocuments(Query collection){
    collection.get().then((value) {
      collectionState = value; // store collection state to set where to start next
      value.docs.forEach((element) {
        print('getDocuments ${element.data()}');
        setState(() {
          listDocument.add(DocObj(DocObj.setDocDetails(element.data())));
        });
      });
    });
  }
}

要解析文档中的数据,您可以为您的对象创建一个模型。

class DocObj {
  var documentName;

  DocObj(DocObj doc) {
    this.documentName = doc.getDocName();
  }

  dynamic getDocName() => documentName;

  DocObj.setDocDetails(Map<dynamic, dynamic> doc)
      : documentName = doc['name'];
}

该示例处理来自 Firestore 的这些数据。

firestore dashboard

这是应用程序运行时的外观。

demo

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter:从 firestore 延迟加载数据 的相关文章

随机推荐