FirestoreListView<Document> constructor
FirestoreListView<Document> ({
- Key? key,
- required Query<
Document> query, - required FirestoreItemBuilder<
Document> itemBuilder, - int pageSize = 10,
- FirestoreLoadingBuilder? loadingBuilder,
- FirestoreErrorBuilder? errorBuilder,
- Axis scrollDirection = Axis.vertical,
- bool reverse = false,
- ScrollController? controller,
- bool? primary,
- ScrollPhysics? physics,
- bool shrinkWrap = false,
- EdgeInsetsGeometry? padding,
- double? itemExtent,
- Widget? prototypeItem,
- bool addAutomaticKeepAlives = true,
- bool addRepaintBoundaries = true,
- bool addSemanticIndexes = true,
- double? cacheExtent,
- int? semanticChildCount,
- DragStartBehavior dragStartBehavior = DragStartBehavior.start,
- ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
- String? restorationId,
- Clip clipBehavior = Clip.hardEdge,
A ListView.builder that obtains its items from a Firestore query.
As an example, consider the following collection:
class Movie {
Movie({required this.title, required this.genre});
Movie.fromJson(Map<String, Object?> json)
: this(
title: json['title']! as String,
genre: json['genre']! as String,
);
final String title;
final String genre;
Map<String, Object?> toJson() {
return {
'title': title,
'genre': genre,
};
}
}
final moviesCollection = FirebaseFirestore.instance.collection('movies').withConverter<Movie>(
fromFirestore: (snapshot, _) => Movie.fromJson(snapshot.data()!),
toFirestore: (movie, _) => movie.toJson(),
);
Using FirestoreListView, we can now show the list of movies by writing:
FirestoreListView<Movie>(
query: moviesCollection.orderBy('title'),
itemBuilder: (context, snapshot) {
Movie movie = snapshot.data();
return Text(movie.title);
},
)
For advanced UI use-cases, consider switching to FirestoreQueryBuilder.
Implementation
FirestoreListView({
Key? key,
required Query<Document> query,
required FirestoreItemBuilder<Document> itemBuilder,
int pageSize = 10,
FirestoreLoadingBuilder? loadingBuilder,
FirestoreErrorBuilder? errorBuilder,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
bool shrinkWrap = false,
EdgeInsetsGeometry? padding,
double? itemExtent,
Widget? prototypeItem,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double? cacheExtent,
int? semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior =
ScrollViewKeyboardDismissBehavior.manual,
String? restorationId,
Clip clipBehavior = Clip.hardEdge,
}) : super(
key: key,
query: query,
pageSize: pageSize,
builder: (context, snapshot, _) {
if (snapshot.isFetching) {
return loadingBuilder?.call(context) ??
const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError && errorBuilder != null) {
return errorBuilder(
context,
snapshot.error!,
snapshot.stackTrace!,
);
}
return ListView.builder(
itemCount: snapshot.docs.length,
itemBuilder: (context, index) {
final isLastItem = index + 1 == snapshot.docs.length;
if (isLastItem && snapshot.hasMore) snapshot.fetchMore();
final doc = snapshot.docs[index];
return itemBuilder(context, doc);
},
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
itemExtent: itemExtent,
prototypeItem: prototypeItem,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries,
addSemanticIndexes: addSemanticIndexes,
cacheExtent: cacheExtent,
semanticChildCount: semanticChildCount,
dragStartBehavior: dragStartBehavior,
keyboardDismissBehavior: keyboardDismissBehavior,
restorationId: restorationId,
clipBehavior: clipBehavior,
);
},
);