使用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
相关产品推荐
相关产品推荐

