Firebase 在Flatter中创建搜索栏而不需要对Cloud Firestore进行不必要的调用的正确方法是什么?
我正在尝试将搜索栏添加到我的颤振应用程序中。我的目标是使用它来过滤ListView中的项目列表。我正在使用CloudFireStore作为数据库部件,我希望利用它的能力通过其快照系统实时更新数据列表 这是我现在拥有的。我已经尽可能地简化了,如果代码很难看,我很抱歉:Firebase 在Flatter中创建搜索栏而不需要对Cloud Firestore进行不必要的调用的正确方法是什么?,firebase,flutter,google-cloud-firestore,Firebase,Flutter,Google Cloud Firestore,我正在尝试将搜索栏添加到我的颤振应用程序中。我的目标是使用它来过滤ListView中的项目列表。我正在使用CloudFireStore作为数据库部件,我希望利用它的能力通过其快照系统实时更新数据列表 这是我现在拥有的。我已经尽可能地简化了,如果代码很难看,我很抱歉: // This controller handles the search string. final TextEditingController _filter = new TextEditingController();
// This controller handles the search string.
final TextEditingController _filter = new TextEditingController();
ListView _listView;
@override
void initState() {
super.initState();
// The widget is rebuilt every time the search string changes.
// I tried to use _listView.build(context) instead but it does not work.
_filter.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _buildStream(_user),
builder: (context, snapshot) {
// Filter the snapshot documents.
var itemList = new List<MyItem>();
var allDocuments = snapshot.data.documents;
for (var i = 0; i < allDocuments.length; i++) {
var documentSnapshot = allDocuments[i];
MyItem item = MyItem.fromSnapshot(documentSnapshot);
if (item.name.contains(_filter.text)) itemList.add(item);
}
_listView = ListView.builder(
itemCount: itemList.length,
itemBuilder: (context, i) =>
_buildListItem(context, itemList[i], i),
);
return _listView;
});
}
Stream<QuerySnapshot> _buildStream(User user) {
return Firestore.instance
.collection('items')
.where('testId', isEqualTo: user.ID)
.snapshots();
}
基本上,我在StreamBuilder的builder中创建了过滤部分。
这段代码给出了我想要的结果,但我担心的是,每次在搜索栏中添加或删除一封信时,它都会调用Firestore。就性能而言,这不是最优的,而且据我所知,每次用户更改搜索字符串时,Firestore都会向我收费,即使相同的项目会一次又一次地返回。我知道通常Firestore快照能够实时更新,并且您只会因为与以前快照的差异而收取费用,但我认为在这种情况下不起作用,因为每次有人更改搜索字符串时,都会重新生成整个小部件
显然,在buildStream中进行过滤会更干净,但在计费方面我仍然会遇到同样的问题。
在构建器中这样做似乎是唯一的选择
我无法找到一种方法来阻止重建整个小部件并避免这些不必要的调用。
有办法吗?我在小部件初始化期间构建了流
// This controller handles the search string.
final TextEditingController _filter = new TextEditingController();
ListView _listView;
Stream<QuerySnapshot> _stream; // <-------------------- ADDED THIS
@override
void initState() {
super.initState();
_stream = _buildStream(_user); // <-------------------- ADDED THIS
// The widget is rebuilt every time the search string changes.
// I tried to use _listView.build(context) instead but it does not work.
_filter.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: _stream, // <-------------------- CHANGED THIS
builder: (context, snapshot) {
// Filter the snapshot documents.
var itemList = new List<MyItem>();
var allDocuments = snapshot.data.documents;
for (var i = 0; i < allDocuments.length; i++) {
var documentSnapshot = allDocuments[i];
MyItem item = MyItem.fromSnapshot(documentSnapshot);
if (item.name.contains(_filter.text)) itemList.add(item);
}
_listView = ListView.builder(
itemCount: itemList.length,
itemBuilder: (context, i) =>
_buildListItem(context, itemList[i], i),
);
return _listView;
});
}
Stream<QuerySnapshot> _buildStream(User user) {
return Firestore.instance
.collection('items')
.where('testId', isEqualTo: user.ID)
.snapshots();
}
我的数据列表上仍然有实时更新,但没有对Firestore进行不必要的调用