Я хочу создать экран разбиения на страницы, используя Bloc, из базы данных Firestore. Экран должен обновляться при изменении документа.
Мой FirestoreProviderApi
получает запросы на выборку от блока Bloc. После извлечения документов из Firestore он отправляет их обратно в блок с помощью Stream
.
FirestoreProviderApi
:
final _pollOverviewStreamController = BehaviorSubject<QuerySnapshot>();
@override
Stream<QuerySnapshot> getOverviewPolls<QuerySnapshot>() =>
_pollOverviewStreamController.asBroadcastStream().cast();
@override
Future<void> fetchFirstOverviewPolls() async {
_overviewPollsRef.limit(5).snapshots().listen((querySnapshot) {
_pollOverviewStreamController.add(querySnapshot);
});
}
@override
Future<void> fetchNextOverviewPolls() async {
if (_pollOverviewStreamController.value.docs.isEmpty) return;
final lastDoc = _pollOverviewStreamController.value.docs.last;
_overviewPollsRef
.startAfterDocument(lastDoc)
.limit(5)
.snapshots()
.listen((querySnapshot) {
_pollOverviewStreamController.add(querySnapshot);
});
}
При изменении документа я хочу обновить свой список документов.
Прямо сейчас, всякий раз, когда происходит изменение, к потоку добавляется новый QuerySnapshot (вместо замены старого). Есть ли способ объединить несколько слушателей в один и тот же поток, собирая только самые свежие данные?
CombineLatestStream
излучает, только если все потоки заканчиваются.
Кажется, то, что я ищу, невозможно. Я нашел альтернативный учебник, который объясняет, как решить эту проблему другим способом fillstacks.com/post/…
Я нашел хорошую документацию о том, как реализовать разбиение на страницы в реальном времени с использованием Firestore (было реализовано, работает как шарм).
Реализация Youtube: Flutter и Firestore Пагинация в реальном времени.
Шаги высокого уровня:
final List<DocumentSnapshot> _overviewPolls = [];
@override
Future<void> fetchOverviewPolls(
[int firstFetchLimit = 1, int nextFetchLimit = 1]) async {
Query overviewPollsQuery = _overviewPollsRef.limit(firstFetchLimit);
if (_overviewPolls.isNotEmpty) {
overviewPollsQuery = overviewPollsQuery
.startAfterDocument(_overviewPolls.last)
.limit(nextFetchLimit);
}
overviewPollsQuery.snapshots().listen((querySnapshot) {
if (querySnapshot.docs.isNotEmpty) {
for (final doc in querySnapshot.docs) {
int index = _overviewPolls.indexWhere((d) => d.id == doc.id);
// if already exists - update poll
if (index >= 0) {
_overviewPolls[index] = doc;
}
// if new document - add poll
else {
_overviewPolls.add(doc);
}
}
_pollOverviewStreamController.add(_overviewPolls);
}
});
}
Обратите внимание, что если вы используете orderBy
при запросе вашего снимка, любое обновление в поле заказа приведет к переупорядочению всего списка элементов. Более того, в некоторых случаях он будет автоматически получать больше элементов (поскольку мы используем ограничение для каждого снимка, а список элементов переупорядочивается, некоторым снимкам может потребоваться получить больше элементов, чтобы заполнить его ограничение).
вы можете объединить несколько потоков в один поток, который дает самые последние данные, используя RxDart.