Я пытаюсь добавить панель поиска в свое приложение Flutter. Моя цель - использовать его для фильтрации списка элементов в ListView. Я использую Cloud Firestore для части базы данных, и я хочу использовать ее возможность обновлять список данных в режиме реального времени с помощью его системы моментальных снимков.
Вот что у меня есть сейчас. Я попытался сделать его максимально простым, поэтому извините, если код уродлив:
// 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. Этот код дает мне желаемый результат, но меня беспокоит тот факт, что он будет вызывать Firestore каждый раз, когда письмо добавляется или удаляется в строке поиска. Это не является оптимальным с точки зрения производительности, и, как я понимаю, Firestore будет выставлять мне счета каждый раз, когда пользователь изменяет строку поиска, даже если одни и те же элементы возвращаются снова и снова. Я знаю, что обычно снимки Firestore могут обновляться в режиме реального времени, и вы платите только за различия с предыдущим снимком, но я не думаю, что это работает в этом случае, потому что весь виджет перестраивается каждый раз, когда кто-то изменяет строку поиска.
Очевидно, что выполнять фильтрацию в _buildStream было бы чище, но у меня все еще будет та же проблема с биллингом. Выполнение этого в компоновщике, кажется, является единственным вариантом.
Я не могу найти способ предотвратить перестройку всего виджета и избежать этих ненужных вызовов. Есть ли способ сделать это?