skip to Main Content

I am wondering how I can improve the following code to make it more efficient and get your tips on what to add/discard. In the current implementation, I am storing all the products in the _data list which is a list of DocumentSnapshot objects that represent the products retrieved from the database.. I feel like this is pretty inefficient.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:shopping_cs308_project/models/product_model.dart';

class ProductsList extends StatefulWidget {
  const ProductsList({super.key});

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

class ProductsListState extends State<ProductsList> {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  late Query _query;
  late ScrollController _scrollController;

  final List<DocumentSnapshot> _data = [];
  bool _isLoading = false;
  bool _hasMoreData = true;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController()..addListener(_scrollListener);
    _query =
        _db.collection('products').orderBy('date', descending: true).limit(10);
    _loadMoreData();
  }

  void _scrollListener() {
    if (_scrollController.offset >=
            _scrollController.position.maxScrollExtent &&
        !_scrollController.position.outOfRange) {
      _loadMoreData();
    }
  }

  Future<void> _loadMoreData() async {
    if (!_hasMoreData || _isLoading) return;
    _isLoading = true;

    final lastVisible = _data.isNotEmpty ? _data.last : null;
    Query query = _query;
    if (lastVisible != null) {
      query = query.startAfterDocument(lastVisible);
    }
    final querySnapshot =
        await query.get(const GetOptions(source: Source.server));
    final newData = querySnapshot.docs;
    setState(() {
      _data.addAll(newData);
      _hasMoreData = newData.length == 10;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
        controller: _scrollController,
        itemCount: _data.length + (_hasMoreData ? 1 : 0),
        itemBuilder: (context, index) {
          if (index == _data.length) {
            return _buildLoader();
          } else {
            final product = ProductModel.fromJson(
                _data[index].data() as Map<String, dynamic>);
            return ListTile(
              title: Text(product.title),
              subtitle: Text(product.description),
              trailing: Text('$${product.price}'),
            );
          }
        },
      ),
    );
  }

  Widget _buildLoader() {
    return _isLoading
        ? const Padding(
            padding: EdgeInsets.all(16.0),
            child: Center(child: CircularProgressIndicator()),
          )
        : Container();
  }
}

2

Answers


  1. Try this:

    This will help you optimise the pagination of Firestore data

    paginate_firestore

    enter image description here

    Login or Signup to reply.
  2. with flutter use this official firebase package to efficiently use the firestore.
    It addresses issues like pagination an more

    https://pub.dev/packages/firebase_ui_firestore

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search