能否使用Dio包处理HTTP请求,并用Shared Preferences包实现缓存?
这是Flutter生态里非常常见的组合方案——Dio负责HTTP请求的发送、拦截、响应处理等核心逻辑,Shared Preferences则用来持久化存储轻量的缓存数据(比如接口响应的JSON字符串、过期时间标记等)。下面是具体的实现思路和代码示例:
1. 先添加依赖
在项目的pubspec.yaml中引入两个包的最新稳定版:
dependencies: flutter: sdk: flutter dio: ^5.4.0 # 请替换为当前最新稳定版 shared_preferences: ^2.2.2 # 请替换为当前最新稳定版
执行flutter pub get完成依赖安装。
2. 核心实现思路
- 发起请求前,先检查Shared Preferences中是否存在对应请求的缓存,且缓存未过期
- 如果缓存有效,直接返回缓存数据;如果缓存过期或不存在,用Dio发起真实请求,拿到响应后将数据和过期时间存入Shared Preferences
3. 具体代码实现
第一步:封装缓存管理工具类
这个类负责处理Shared Preferences的缓存读写、过期判断等操作:
import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert'; class HttpCacheManager { static const String _cacheKeyPrefix = 'http_cache_'; // 存储缓存,expireTime单位为秒 static Future<void> saveCache(String url, dynamic data, int expireTime) async { final prefs = await SharedPreferences.getInstance(); final cacheContent = { 'responseData': data, 'expireTimestamp': DateTime.now().millisecondsSinceEpoch + expireTime * 1000, }; await prefs.setString(_cacheKeyPrefix + url, json.encode(cacheContent)); } // 获取缓存,返回null代表无缓存或已过期 static Future<dynamic?> getCache(String url) async { final prefs = await SharedPreferences.getInstance(); final cacheString = prefs.getString(_cacheKeyPrefix + url); if (cacheString == null) return null; final cacheContent = json.decode(cacheString); final currentTimestamp = DateTime.now().millisecondsSinceEpoch; if (currentTimestamp > cacheContent['expireTimestamp']) { // 缓存过期,删除旧缓存并返回null await prefs.remove(_cacheKeyPrefix + url); return null; } return cacheContent['responseData']; } // 清除指定URL的缓存 static Future<void> clearSingleCache(String url) async { final prefs = await SharedPreferences.getInstance(); await prefs.remove(_cacheKeyPrefix + url); } // 清除所有HTTP缓存 static Future<void> clearAllCache() async { final prefs = await SharedPreferences.getInstance(); final allKeys = prefs.getKeys(); for (final key in allKeys) { if (key.startsWith(_cacheKeyPrefix)) { await prefs.remove(key); } } } }
第二步:结合Dio实现带缓存的请求
封装API服务类,在请求中集成缓存逻辑:
import 'package:dio/dio.dart'; class ApiService { final Dio _dio = Dio(BaseOptions(baseUrl: 'https://your-api-base-url.com')); // 带缓存的GET请求,默认缓存5分钟(300秒) Future<dynamic> getWithCache(String url, {int expireTime = 300}) async { // 优先读取缓存 final cacheData = await HttpCacheManager.getCache(url); if (cacheData != null) { return cacheData; } // 缓存无效,发起真实请求 final response = await _dio.get(url); if (response.statusCode == 200) { // 将响应数据存入缓存 await HttpCacheManager.saveCache(url, response.data, expireTime); return response.data; } else { throw Exception('请求失败:${response.statusCode}'); } } }
4. 注意事项
- Shared Preferences仅适合存储轻量文本数据(比如JSON字符串),如果需要缓存大文件(如图片、音频),建议使用
path_provider配合本地文件存储 - 如果请求包含参数(比如GET的query、POST的body),缓存key需要包含参数信息(比如对参数做哈希处理),避免不同参数的请求复用同一缓存
- 可根据接口特性灵活调整过期时间,部分实时性要求高的接口可以跳过缓存逻辑
- 注意处理JSON序列化/反序列化的异常,比如非标准JSON格式的响应需要额外处理
内容的提问来源于stack exchange,提问作者Lils Don
相关产品推荐
相关产品推荐

