使用streambuilder进行扑火分页 [英] flutter firestore pagination using streambuilder

查看:23
本文介绍了使用streambuilder进行扑火分页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,我想在我的列表中使用分页.并且列表数据来自 firebase.我不确定如何使用流构建器对数据进行分页.现在我通过在 didChangeDependencies() 函数中调用 getdocuments 来进行分页.但在添加新数据后,列表不会更新.如果有人可以提供帮助,那么这对我来说会很棒.这就是我现在正在做的事情..

hello i am trying to use pagination in my list. and the list data is coming from firebase. i am not sure how to paginate data using stream builder. now i am doing the pagination by calling getdocuments in the didChangeDependencies() function. but after adding new data the list is not updated. if anyone can help then it will be great for me. here is what i am doing now..

 didChangeDependencies() {
    super.didChangeDependencies();

   getProducts();

    _scrollController.addListener(() {
      double maxScroll = _scrollController.position.maxScrollExtent;
      double currentScroll = _scrollController.position.pixels;
      double delta = MediaQuery.of(context).size.height * 0.20;
      if (maxScroll - currentScroll <= delta) {
        getProducts();
      }
    });
  }

  getProducts() async {
    if (!hasMore) {
      return;
    }
    if (isLoading) {
      return;
    }
    setState(() {
      isLoading = true;
    });
    QuerySnapshot querySnapshot;
    if (lastDocument == null) {
      querySnapshot = await firestore
          .collection('products')
          .limit(documentLimit)
          .orderBy('timestamp', descending: true)
          .getDocuments();
    } else {
      querySnapshot = await firestore
          .collection('products')
          .startAfterDocument(lastDocument)
          .limit(documentLimit)
          .orderBy('timestamp', descending: true)
          .getDocuments();
    }
    if (querySnapshot.documents.length < documentLimit) {
      hasMore = false;
    }
    if (querySnapshot.documents.isNotEmpty) {
      lastDocument =
          querySnapshot.documents[querySnapshot.documents.length - 1];
      products.addAll(querySnapshot.documents);
      setState(() {
        isLoading = false;
      });
    }
  }

推荐答案

试试下面的代码:

class ProductList extends StatefulWidget {
  @override
  _ProductListState createState() => _ProductListState();
}

class _ProductListState extends State<ProductList> {
  StreamController<List<DocumentSnapshot>> _streamController =
  StreamController<List<DocumentSnapshot>>();
  List<DocumentSnapshot> _products = [];

  bool _isRequesting = false;
  bool _isFinish = false;

  void onChangeData(List<DocumentChange> documentChanges) {
    var isChange = false;
    documentChanges.forEach((productChange) {
      if (productChange.type == DocumentChangeType.removed) {
        _products.removeWhere((product) {
          return productChange.document.documentID == product.documentID;
        });
        isChange = true;
      } else {

        if (productChange.type == DocumentChangeType.modified) {
          int indexWhere = _products.indexWhere((product) {
            return productChange.document.documentID == product.documentID;
          });

          if (indexWhere >= 0) {
            _products[indexWhere] = productChange.document;
          }
          isChange = true;
        }
      }
    });

    if(isChange) {
      _streamController.add(_products);
    }
  }

  @override
  void initState() {
    Firestore.instance
        .collection('products')
        .snapshots()
        .listen((data) => onChangeData(data.documentChanges));

    requestNextPage();
    super.initState();
  }

  @override
  void dispose() {
    _streamController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    return NotificationListener<ScrollNotification>(
        onNotification: (ScrollNotification scrollInfo) {
          if (scrollInfo.metrics.maxScrollExtent == scrollInfo.metrics.pixels) {
            requestNextPage();
          }
          return true;
        },
        child: StreamBuilder<List<DocumentSnapshot>>(
          stream: _streamController.stream,
          builder: (BuildContext context,
              AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
            if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
            switch (snapshot.connectionState) {
              case ConnectionState.waiting:
                return new Text('Loading...');
              default:
                log("Items: " + snapshot.data.length.toString());
                return ListView.separated(
                  separatorBuilder: (context, index) => Divider(
                    color: Colors.black,
                  ),
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) => Padding(
                    padding: const EdgeInsets.symmetric(vertical: 32),
                    child: new ListTile(
                      title: new Text(snapshot.data[index]['name']),
                      subtitle: new Text(snapshot.data[index]['description']),
                    ),
                  ),
                );
            }
          },
        ));
  }

  void requestNextPage() async {
    if (!_isRequesting && !_isFinish) {
      QuerySnapshot querySnapshot;
      _isRequesting = true;
      if (_products.isEmpty) {
        querySnapshot = await Firestore.instance
            .collection('products')
            .orderBy('index')
            .limit(5)
            .getDocuments();
      } else {
        querySnapshot = await Firestore.instance
            .collection('products')
            .orderBy('index')
            .startAfterDocument(_products[_products.length - 1])
            .limit(5)
            .getDocuments();
      }

      if (querySnapshot != null) {
        int oldSize = _products.length;
        _products.addAll(querySnapshot.documents);
        int newSize = _products.length;
        if (oldSize != newSize) {
          _streamController.add(_products);
        } else {
          _isFinish = true;
        }
      }
      _isRequesting = false;
    }
  }
}

产品项目的 JSON:

{
  "index": 1,
  "name": "Pork",
  "description": "Thịt heo/lợn"
}

链接 Github 示例: https://github.com/simplesoft-duongdt3/flutter_firestore_paging

这篇关于使用streambuilder进行扑火分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆