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

Flutter中Stream未触发Widget重建,HackerNews接口数据无法正常展示问题

问题核心原因

  1. 异步时序问题:你在ListView.builder的itemBuilder中调用fetchItem往stream塞id,stream的处理是异步的,不会立刻更新items流的缓存Map。当NewsListTile首次build时,缓存Map里还没有对应id的key,直接用[]!取到的是null,传给FutureBuilder的future参数为null时,会永远处于hasData = false的状态。
  2. 缓存Map引用不变的潜在问题:ScanStreamTransformer中直接修改原有Map对象并返回,虽然默认stream不会拦截相同引用的事件,但如果后续加了distinct逻辑、或者框架层有对象相等判断,会导致下游收不到更新事件。
  3. 缺少异常处理:如果API请求、JSON解析环节抛出异常,FutureBuilder的hasError会为true,你没有对应判断分支,也会一直显示加载中。

修复方案

1. 修改stories_bloc中的转换器逻辑,每次返回新的Map实例

_itemsTransformer() {
  return ScanStreamTransformer(
    (Map<int, Future<ItemModel>> cache, int id, index) {
      // 基于旧缓存创建新Map,避免引用不变导致的问题
      final newCache = Map<int, Future<ItemModel>>.from(cache);
      newCache[id] = _newsRepository.fetchItem(id);
      return newCache;
    },
    <int, Future<ItemModel>>{},
  );
}

2. 修改NewsListTile中的逻辑,增加key存在判断和异常处理

class NewsListTile extends StatelessWidget {
  final int itemId;
  const NewsListTile({required this.itemId});
  
  @override
  Widget build(BuildContext context) {
    final bloc = StoriesBlocProvider.of(context);
    return StreamBuilder(
      stream: bloc.items,
      builder: (context, AsyncSnapshot<Map<int, Future<ItemModel>>> snapshot) {
        if (!snapshot.hasData) {
          return const Text('Fetching item');
        }
        // 先判断当前id是否已经加入缓存
        if (!snapshot.data!.containsKey(itemId)) {
          return Text('Still loading item $itemId');
        }
        return FutureBuilder(
          future: snapshot.data![itemId]!,
          builder: (context, AsyncSnapshot<ItemModel> itemSnapshot) {
            // 新增错误处理,方便排查请求/解析问题
            if (itemSnapshot.hasError) {
              return Text('加载失败 $itemId: ${itemSnapshot.error}');
            }
            if (!itemSnapshot.hasData) {
              return Text('Still loading item $itemId');
            }
            return Text(itemSnapshot.data!.title);
          },
        );
      },
    );
  }
}

额外检查项

确认你的ItemModel.fromJson方法字段映射正确,没有拼写错误,避免JSON解析抛出未捕获的异常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 22:45:03