You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否使用Dio包处理HTTP请求,并用Shared Preferences包实现缓存?

当然可以!用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:02:40