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

Flutter开发中如何避免重复编写StreamBuilder代码?

三层StreamBuilder封装实现方案

失效原因

此前方案失效的核心原因是仅将子Widget作为静态参数传入封装组件,没有暴露三层Stream获取到的数据给子组件,无法完成数据传递。

实现思路

使用Widget构建器函数替代直接传入子Widget,将三层Stream返回的列表数据整合后作为参数传递给构建器,使用侧直接在构建器中接收数据生成业务UI即可。

封装代码

// 整合三层Stream返回的数据结构
class TripleStreamData<T1, T2, T3> {
  final List<T1>? firstList;
  final List<T2>? secondList;
  final List<T3>? thirdList;
  final bool isLoading;
  final Object? error;

  TripleStreamData({
    this.firstList,
    this.secondList,
    this.thirdList,
    this.isLoading = true,
    this.error,
  });
}

// 封装后的三层StreamBuilder通用组件
class TripleStreamBuilder<T1, T2, T3> extends StatelessWidget {
  final Stream<List<T1>> firstStream;
  final Stream<List<T2>> secondStream;
  final Stream<List<T3>> thirdStream;
  // 数据回调构建器,封装组件将数据通过该参数回传给使用侧
  final Widget Function(BuildContext context, TripleStreamData<T1, T2, T3> data) builder;

  const TripleStreamBuilder({
    super.key,
    required this.firstStream,
    required this.secondStream,
    required this.thirdStream,
    required this.builder,
  });

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<T1>>(
      stream: firstStream,
      builder: (context, firstSnapshot) {
        return StreamBuilder<List<T2>>(
          stream: secondStream,
          builder: (context, secondSnapshot) {
            return StreamBuilder<List<T3>>(
              stream: thirdStream,
              builder: (context, thirdSnapshot) {
                // 统一处理错误状态
                if (firstSnapshot.hasError || secondSnapshot.hasError || thirdSnapshot.hasError) {
                  return builder(
                    context,
                    TripleStreamData(
                      error: firstSnapshot.error ?? secondSnapshot.error ?? thirdSnapshot.error,
                      isLoading: false,
                    ),
                  );
                }
                // 统一处理加载中状态
                if (firstSnapshot.connectionState == ConnectionState.waiting ||
                    secondSnapshot.connectionState == ConnectionState.waiting ||
                    thirdSnapshot.connectionState == ConnectionState.waiting) {
                  return builder(context, TripleStreamData(isLoading: true));
                }
                // 所有数据加载完成后回传给使用侧
                return builder(
                  context,
                  TripleStreamData(
                    firstList: firstSnapshot.data,
                    secondList: secondSnapshot.data,
                    thirdList: thirdSnapshot.data,
                    isLoading: false,
                  ),
                );
              },
            );
          },
        );
      },
    );
  }
}

使用示例

TripleStreamBuilder<User, Order, Product>(
  firstStream: userListStream, // 替换为你的第一个列表Stream
  secondStream: orderListStream, // 替换为你的第二个列表Stream
  thirdStream: productListStream, // 替换为你的第三个列表Stream
  builder: (context, data) {
    if (data.isLoading) {
      return const Center(child: CircularProgressIndicator());
    }
    if (data.error != null) {
      return Center(child: Text('加载出错:${data.error.toString()}'));
    }
    // 直接使用三个列表数据构建业务UI
    final userList = data.firstList!;
    final orderList = data.secondList!;
    final productList = data.thirdList!;
    return ListView(
      children: [
        Text('用户总数:${userList.length}'),
        Text('订单总数:${orderList.length}'),
        Text('商品总数:${productList.length}'),
        // 其余业务UI代码
      ],
    );
  },
)

优化建议

  • 若三个Stream无先后依赖关系,可使用StreamZip合并三个Stream减少嵌套层级,提升代码可读性
  • 可根据业务需求自定义加载、错误状态的默认UI,进一步减少重复代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:54:02