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

Flutter用StreamBuilder替代FutureBuilder突破Firestore whereIn10条限制

实现方案

核心逻辑分为两部分:一是拆分查询参数解决Firestore whereIn 最多10个参数的限制,二是改造为Stream监听实现数据自动更新。


1. 改造Bloc层数据逻辑

final FirebaseFirestore firestore = FirebaseFirestore.instance;

// 返回用户点赞内容的Stream
Stream<List<QueryDocumentSnapshot>> getLovedContentsStream() async* {
  // 获取当前登录用户uid
  SharedPreferences sp = await SharedPreferences.getInstance();
  String _uid = sp.getString('uid') ?? '';
  if(_uid.isEmpty) {
    yield [];
    return;
  }

  // 监听用户文档变化,点赞/取消点赞会自动触发重查
  await for (DocumentSnapshot userSnap in firestore.collection('users').doc(_uid).snapshots()) {
    List lovedTimestamps = userSnap.get('loved items') ?? [];
    if(lovedTimestamps.isEmpty) {
      yield [];
      continue;
    }

    // 拆分点赞列表为每10个一组,突破whereIn参数限制
    List<List> chunks = [];
    for (int i = 0; i < lovedTimestamps.length; i += 10) {
      int end = (i + 10 < lovedTimestamps.length) ? i + 10 : lovedTimestamps.length;
      chunks.add(lovedTimestamps.sublist(i, end));
    }

    // 分批发起查询合并结果
    List<Future<QuerySnapshot>> queryFutures = chunks.map((chunk) {
      return firestore.collection('contents').where('timestamp', whereIn: chunk).get();
    }).toList();

    List<QuerySnapshot> allQueryResult = await Future.wait(queryFutures);
    List<QueryDocumentSnapshot> filteredData = [];
    for (var snap in allQueryResult) {
      filteredData.addAll(snap.docs);
    }

    // 按用户点赞列表顺序排序,避免展示顺序混乱
    filteredData.sort((a, b) {
      int indexA = lovedTimestamps.indexOf(a.get('timestamp'));
      int indexB = lovedTimestamps.indexOf(b.get('timestamp'));
      return indexA.compareTo(indexB);
    });

    yield filteredData;
    notifyListeners();
  }
}

2. 改造UI层渲染逻辑

将原有FutureBuilder替换为StreamBuilder即可,原有_buildList方法无需任何修改:

body: sb.guestUser == true
    ? EmptyPage(
        icon: FontAwesomeIcons.heart,
        title: 'No wallpapers found.\n Sign in to access this feature',
      )
    : StreamBuilder<List<QueryDocumentSnapshot>>(
        stream: context.watch<BookmarkBloc>().getLovedContentsStream(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            if (snapshot.data!.isEmpty)
              return EmptyPage(
                icon: FontAwesomeIcons.heart,
                title: 'No wallpapers found',
              );
            return _buildList(snapshot);
          } else if (snapshot.hasError) {
            return Center(
              child: Text(snapshot.error.toString()),
            );
          }

          return Center(
            child: CupertinoActivityIndicator(),
          );
        },
      ),

该实现同时支持拉取超过10条的点赞内容,且用户新增/取消点赞后页面会自动同步更新,无需手动触发刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 21:09:01