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
Try this:
This will help you optimise the pagination of Firestore data
paginate_firestore
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