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

使用Provider时FutureBuilder数据未就绪为何不执行加载分支?

解决FutureBuilder数据未就绪分支不执行的问题

核心原因

每次PagerModel的page值变更时,build方法会被重新触发,导致fetchProfiles(pagerModel.page)被反复调用,生成新的Future实例。FutureBuilder会立即丢弃之前的Future,转而监听新的Future,结果就是Future还没进入ConnectionState.waiting状态就被替换,导致你标注的else分支(对应加载状态)根本没机会执行。

未使用Provider时,build不会频繁触发,Future能正常走完从pending到完成的流程,所以加载状态能正常显示。

解决方案

1. 将Future的创建与缓存移到ViewModel(PagerModel)中

把数据请求逻辑封装到PagerModel里,确保同一个page只生成一次Future,避免每次build都创建新Future:

class PagerModel extends ChangeNotifier {
  int _page = 1;
  Future<List<ProfileData>>? _currentRequestFuture;
  final WebService _webService = locator<WebService>();

  int get page => _page;

  // 获取当前页数据,缓存Future避免重复请求
  Future<List<ProfileData>> getCurrentPageProfiles() {
    // 如果当前没有正在进行的请求,创建新请求
    if (_currentRequestFuture == null) {
      _currentRequestFuture = _webService.fetchProfiles(Gender.female, _page);
    }
    return _currentRequestFuture!;
  }

  // 切换到下一页,清空旧的请求Future
  void nextPage() {
    _page++;
    _currentRequestFuture = null;
    notifyListeners();
  }
}

2. 修改FutureBuilder的使用逻辑

在build中调用ViewModel提供的缓存Future,并显式判断connectionState,逻辑更清晰:

@override
Widget build(BuildContext context) {
  final pagerModel = context.watch<PagerModel>();
  return FutureBuilder<List<ProfileData>>(
    future: pagerModel.getCurrentPageProfiles(),
    builder: (context, snapshot) {
      // 显式判断加载状态
      if (snapshot.connectionState == ConnectionState.waiting) {
        debugPrint('显示加载中');
        return const Scaffold(
          appBar: PaginationAppBar(Gender.female),
          body: CircularProgressIndicator(),
        );
      } 
      // 错误状态
      else if (snapshot.hasError) {
        return _processError(snapshot);
      } 
      // 数据就绪状态
      else if (snapshot.hasData) {
        final data = snapshot.data;
        debugPrint('snapshot data length ${snapshot.data?.length}');
        if (data!.isEmpty) {
          return const ErrorWithMessage(message: 'data loading error');
        }
        return Scaffold(
          appBar: const PaginationAppBar(Gender.female),
          body: ProfileGrid(data),
        );
      } 
      // 兜底情况
      else {
        return const Scaffold(
          appBar: PaginationAppBar(Gender.female),
          body: CircularProgressIndicator(),
        );
      }
    },
  );
}

3. 额外注意事项

  • 不要在build方法中直接创建Future,这会导致每次build都生成新实例,破坏FutureBuilder的状态跟踪
  • 显式判断connectionState比依赖else分支更可靠,能覆盖所有状态场景
  • 如果需要支持下拉刷新或强制刷新,可以在ViewModel中添加方法手动清空缓存的Future

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:22:47