Flutter启动页API存入SharedPreferences时卡顿无法跳转求助
问题分析
启动页调用API获取64组键值对,存储到SharedPreferences时执行到第47组卡顿,无法跳转至下一页,控制台出现W/ratelimit( 9649): Single process limit 250/s drop 102 lines.警告,核心问题在于异步逻辑处理错误、循环越界和SharedPreferences操作效率低下。
修复步骤
1. 修正API调用的异步等待逻辑
原代码中调用provider.fetchGeneralSetting()时未使用await,导致还未获取到API数据就开始执行存储逻辑,且重复调用了fetchGeneralSetting(),造成不必要的重复请求。修改如下:
api() async { final provider = Provider.of<GeneralSettingProvider>(context, listen: false); // 等待API请求完成 await provider.fetchGeneralSetting(); if (provider.generalSettingModel?.result != null) { SharedPreferences prefs = await SharedPreferences.getInstance(); Map<String, String> settingsMap = {}; // 批量整理键值对 for (int i = 0; i < provider.generalSettingModel!.result!.length; i++) { final key = provider.generalSettingModel!.result![i].key ?? ''; final value = provider.generalSettingModel!.result![i].value ?? ''; if (key.isNotEmpty) { settingsMap[key] = value; } } // 批量存储到SharedPreferences await prefs.setStringMap(settingsMap); // 确保页面未销毁再跳转 if (mounted) { Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const BottomMenuBar())); } } }
2. 修复循环越界问题
原循环条件i <= provider.generalSettingModel!.result!.length会导致索引超出数组范围(数组索引从0开始,最大索引为length-1),改为i < provider.generalSettingModel!.result!.length避免数组越界错误。
3. 优化SharedPreferences存储效率
原代码循环中多次调用setString,每次都是独立的异步IO操作,会导致性能瓶颈。改为先将所有键值对存入Map,再通过setStringMap一次性批量存储,大幅减少IO操作次数。
4. 避免build方法中重复执行日志输出
原build方法中每次都会调用getdata(),而build会频繁触发,导致大量重复日志输出,甚至触发日志速率限制。可以移除getdata()方法,改用Consumer监听Provider状态变化:
@override Widget build(BuildContext context) { return Consumer<GeneralSettingProvider>( builder: (context, provider, child) { if (provider.loading) { debugPrint("===>> Loading..."); } else if (provider.generalSettingModel != null) { debugPrint("===>> ${provider.generalSettingModel!.status}"); } return const Scaffold( body: SingleChildScrollView( child: Column( children: [ Image(image: AssetImage('assets/images/splash-img.png')), ], ), ), ); }, ); }
5. 完善Provider的错误处理(可选)
在Provider的fetchGeneralSetting中添加错误捕获,避免API请求失败导致后续逻辑阻塞:
fetchGeneralSetting() async { _loading = true; notifyListeners(); try { generalSettingModel = await ApiService().generalSetting(); errorMessage = null; } catch (e) { errorMessage = e.toString(); if (kDebugMode) { print("API请求失败: $e"); } } finally { _loading = false; notifyListeners(); } }
关于日志速率限制警告
W/ratelimit...是因为调试日志输出频率超过了系统的单进程日志速率限制(250条/秒),修复上述问题后,日志输出会恢复正常,该警告也会消失。
内容的提问来源于stack exchange,提问作者Himanshu M. Dave

