firebase - 使用streambuilder颤动firestore分页
问题描述
你好我正在尝试在我的列表中使用分页。并且列表数据来自firebase。我不确定如何使用流生成器对数据进行分页。现在我通过在 didChangeDependencies() 函数中调用 getdocuments 来进行分页。但添加新数据后,列表不会更新。如果有人可以提供帮助,那对我来说会很棒。这就是我现在正在做的事情..
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
推荐阅读
- c++ - 解决多个重载
- ignite - Apache Ignite Yarn 部署 HDFS 问题
- go - 为什么在 golang 中写入全局地图时恢复不起作用
- wordpress - 如果 post 存在且 post_meta 存在
- angular - 在 agm 上放置自定义控制按钮
- python - Scikit 学习多元线性回归和多项式特征的系数顺序
- python - 使用底图和 matplotlib 对某个国家/地区的某些城市进行彩色绘图
- discord - 如果消息包含不和谐 py 的表情符号,如何检查 on_message?
- c - if 语句中的多个条件如何工作
- android - Arraylist 在 android 中为空检查