如何避免再次访问Flutter页面时显示CircularProgressIndicator?
解决Flutter Tab页重复加载数据的问题
核心思路是把请求到的数据缓存到页面的状态变量中,只在第一次进入页面时发起网络请求,后续切换标签直接使用本地缓存的数据,避免重复显示加载指示器。
具体修改步骤:
- 在State类中添加缓存变量与加载状态
在你的页面State类里,定义用于缓存用户数据的变量和标记加载状态的变量:
List<User>? _cachedUsers; bool _isLoading = false;
- 初始化时仅加载一次数据
重写initState方法,在页面初始化时调用数据请求方法,并且只有在没有缓存数据时才发起请求:
@override void initState() { super.initState(); _fetchUsers(); } Future<void> _fetchUsers() async { // 已有缓存直接返回,避免重复请求 if (_cachedUsers != null) return; _isLoading = true; setState(() {}); try { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users')); final jsondata = json.decode(response.body); // 直接将JSON数据转为User列表,简化原有的循环写法 _cachedUsers = jsondata.map<User>((data) => User.fromJson(data)).toList(); } catch (e) { // 这里可以添加错误处理逻辑,比如提示用户加载失败 print('加载用户数据出错:$e'); } finally { _isLoading = false; setState(() {}); } }
- 替换FutureBuilder,直接根据缓存状态渲染UI
不再使用FutureBuilder,而是根据_isLoading和_cachedUsers的状态来渲染不同的UI:
@override Widget build(BuildContext context) { // 第一次加载时显示指示器 if (_isLoading) { return const Center(child: CircularProgressIndicator()); } // 加载失败时显示提示 if (_cachedUsers == null) { return const Center(child: Text('加载失败,请稍后重试')); } // 有缓存数据时直接渲染列表 return ListView.builder( itemCount: _cachedUsers!.length, itemBuilder: (context, index) { final user = _cachedUsers![index]; return ListTile( title: Text(user.name.toString()), subtitle: Text(user.email.toString()), leading: CircleAvatar(child: Text(user.id.toString())), ); }, ); }
Todos页面同理处理
对于todos标签页,只需要复制上述逻辑,将_cachedUsers改为_cachedTodos,_fetchUsers改为_fetchTodos,请求地址换成todos的接口即可。
这样修改后,只有第一次进入标签页时会显示加载指示器,后续切换标签都会直接显示本地缓存的数据,不会再重复发起网络请求和显示加载圈。
内容的提问来源于stack exchange,提问作者Irfan Ganatra
相关产品推荐
相关产品推荐

