Flutter中FutureBuilder更新时未显示进度条问题如何解决?
问题原因
出现该现象的核心原因是FutureBuilder的默认行为:当传入的Future更新时,旧数据会一直保留在snapshot.data中直到新Future执行完成。如果你优先判断snapshot.hasData再处理加载逻辑,就会始终展示旧数据。
解决方案
下面提供两种常用实现方式:
方案1:手动维护加载状态(灵活度更高,适合复杂场景)
不需要完全依赖FutureBuilder的内置状态,自己维护数据和加载标识即可:
class _MyWidgetState extends State<MyWidget> { List<String>? _serverData; bool _isLoading = false; // 拉取服务端数据的方法 Future<void> _fetchData() async { // 开始拉取前标记为加载中 setState(() => _isLoading = true); try { // 替换为你的实际服务端请求逻辑 final response = await Future.delayed(const Duration(seconds: 2), () => ['数据1', '数据2', '数据3']); setState(() => _serverData = response); } catch (err) { // 按需添加异常处理逻辑 } finally { // 无论请求成功失败,结束后关闭加载状态 setState(() => _isLoading = false); } } @override void initState() { super.initState(); // 首次进入页面加载数据 _fetchData(); } @override Widget build(BuildContext context) { // 优先判断加载状态,只要是加载中就展示进度条 if (_isLoading) { return const Center(child: CircularProgressIndicator()); } // 无数据展示缺省 if (_serverData == null) { return const Center(child: Text('暂无数据')); } // 正常展示数据 return Column( children: [ ElevatedButton( onPressed: _fetchData, child: const Text('点击刷新数据'), ), ..._serverData!.map((item) => ListTile(title: Text(item))).toList() ], ); } }
方案2:调整FutureBuilder判断顺序(轻量实现,适合简单场景)
如果你不想额外维护状态,只要调整FutureBuilder的判断顺序,优先判断connectionState是否为等待状态即可:
class _MyWidgetState extends State<MyWidget> { Future<List<String>>? _futureData; // 实际的服务端请求逻辑 Future<List<String>> _fetchRemoteData() async { return await Future.delayed(const Duration(seconds: 2), () => ['新数据1', '新数据2', '新数据3']); } @override void initState() { super.initState(); _futureData = _fetchRemoteData(); } // 刷新时更新Future void _handleRefresh() { setState(() { _futureData = _fetchRemoteData(); }); } @override Widget build(BuildContext context) { return FutureBuilder<List<String>>( future: _futureData, builder: (context, snapshot) { // 优先判断是否处于加载中,只要是等待状态就展示进度条 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Center(child: Text('加载失败:${snapshot.error}')); } if (!snapshot.hasData) { return const Center(child: Text('暂无数据')); } final data = snapshot.data!; return Column( children: [ ElevatedButton(onPressed: _handleRefresh, child: const Text('点击刷新')), ...data.map((item) => ListTile(title: Text(item))).toList() ], ); }, ); } }
内容的提问来源于stack exchange,提问作者Manish Raj Yadav
相关产品推荐
相关产品推荐

