You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter调用asBroadcastStream时Firestore变更触发流数据重复问题

问题根因

核心问题出在firestore_service.dart的流实现逻辑,其次存在Provider流重复创建的潜在问题:

  • 你将List<MediaItem> mediaList = []定义在了await for循环的外层,整个流的生命周期里这个列表只会初始化一次。每次Firestore快照更新触发迭代时,新的文档数据会直接追加到已有列表中,不会清空旧数据,导致每次流推送的列表长度都比上一次多一倍,最终出现重复条目。
  • 其次你的mediaProvider.getMedia()方法每次被调用都会生成全新的Firestore监听流,即使转成了广播流,多个页面多次调用时依然会创建多个独立的Firestore监听器,额外消耗资源。
修复方案

1. 修复流数据累加问题

将mediaList的初始化逻辑移到await for循环内部,每次快照更新时都创建全新的空列表填充数据:

Stream<List<MediaItem>> getMedia({
  required String albumId,
  required MediaFilter mediaFilter,
  required String? uid,
}) async* {
  // no filter
  Stream mediaStream = _mediaCollectionReference
      .where('albumId', isEqualTo: albumId)
      .orderBy('createdAt', descending: true)
      .snapshots();
  await for (QuerySnapshot mediaSnapshot in mediaStream) {
    // 每次快照更新都新建空列表,避免累加旧数据
    List<MediaItem> mediaList = [];
    for (var mediaDoc in mediaSnapshot.docs) {
      MediaItem mediaItem = MediaItem.fromData(
          mediaDoc.id, mediaDoc.data() as Map<String, dynamic>);
      mediaList.add(mediaItem);
    }
    yield mediaList;
  }
}

2. 优化Provider流缓存逻辑

在Provider中缓存已创建的流,避免重复生成新的Firestore监听:

// 在Provider中新增成员变量缓存流
Stream<List<MediaItem>>? _mediaStream;

Stream<List<MediaItem>> getMedia() {
  // 已创建过流直接返回,避免重复监听
  if (_mediaStream != null) return _mediaStream!;
  _mediaStream = _firestoreService
      .getMedia(
        albumId: _albumId,
        mediaFilter: _mediaFilter,
        uid: _authService.currentUser!.getId,
      )
      .asBroadcastStream();
  setCurrentState(_mediaStream!);
  return _mediaStream!;
}

// 如果有切换筛选条件、专辑ID的需求,新增重置流的方法
void resetMediaStream() {
  _mediaStream = null;
}

可选加固方案

你也可以在遍历文档时根据MediaItem的ID做去重处理,进一步避免意外的重复数据:

await for (QuerySnapshot mediaSnapshot in mediaStream) {
  Map<String, MediaItem> mediaMap = {};
  for (var mediaDoc in mediaSnapshot.docs) {
    MediaItem mediaItem = MediaItem.fromData(
        mediaDoc.id, mediaDoc.data() as Map<String, dynamic>);
    mediaMap[mediaDoc.id] = mediaItem;
  }
  yield mediaMap.values.toList();
}

内容的提问来源于stack exchange,提问作者Rens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:15:08