使用多个侦听器组合的flutter Firestore实时分页

发布于 2025-01-28 09:53:50 字数 1207 浏览 5 评论 0原文

我想从Firestore数据库创建一个使用Bloc的分页屏幕。屏幕应更新文档更改。

我的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附加到流(而不是更换旧的)上。 是否有一种方法可以将多个听众组合到同一流,仅汇总最新数据?

I want to create a pagination screen, using Bloc, from the Firestore database. The screen should update on document changes.

My FirestoreProviderApi receives fetch requests from the Bloc unit. After fetching the documents from Firestore, it sends them back to the Bloc using a Stream.

The 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);
    });
  }

On document changes, I want to update my list of documents.

Right now, whenever a change occurs, a new QuerySnapshot is appended to the Stream (instead of replacing the old one).
Is there a way to combine multiple listeners to the same Stream, aggregating only the most up-to-date data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

涫野音 2025-02-04 09:53:50

问题解决了。

我找到了如何实施真实的文档 - 使用Firestore的时间分页(已实现,工作就像魅力一样)。

YouTube实现: flutter和flutter and firestore实时分页

高级步骤:

  1. 创建一个类别的文档列表状态变量。
  2. 每次流式传输整个列表
  3. 在快照更改中聆听和迭代,更新/将文档添加到主列表
  4. 如果列表不是空的,则从列表上的最后一个文档中获取。

我的实施:

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 在查询快照时,对订单字段的任何更新都会导致整个列表的重新排序项目。此外,在某些情况下,它将自动获取更多的项目(由于我们使用每个快照的限制,并且重新排序项目列表,因此某些快照可能需要获取更多项目来填补其限制)。

Issue solved.

I found good documentation of how to implement real-time pagination using Firestore (been implemented it, works like a charm).

Youtube implementation: Flutter and Firestore real-time Pagination.

High-level steps:

  1. Create a class-scoped document list state variable.
  2. Stream each time the whole list.
  3. Listen and iterate over snapshot changes, and update/add documents to the main list.
  4. If the list is not empty, then fetch from the last document on the list.

My implementation:

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);
      }
    });
  }

Using orderBy

Note that if you are using orderBy on querying your snapshot, any update to the order's field will cause a reordering of the whole list of items. Moreover, in some cases, it will fetch automatically more items (since we are using a limit for each snapshot, and the list of items is reordered, some snapshots may need to fetch more items to fill its limitation).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文