import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:news_getx/config/cache.dart'; import 'package:news_getx/data/services/storage.dart'; class CacheObject { Response response; int timestamp; CacheObject(this.response) : timestamp = DateTime.now().millisecondsSinceEpoch; @override bool operator ==(Object other) { return response.hashCode == other.hashCode; } @override int get hashCode => response.realUri.hashCode; } class NetCache extends Interceptor { // 为确保迭代器顺序和对象插入时间一致顺序一致,我们使用LinkedHashMap, 默认的字面量{}就是有序的 // 内存缓存 var cache = {}; @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { // refresh标记是否是"下拉刷新" bool refresh = options.extra['refresh'] == true; // 是否磁盘缓存 bool cacheDisk = options.extra['cacheDisk'] == true; // 如果是下拉刷新,先删除相关缓存 if (refresh) { // 如果是下拉刷新,先删除相关缓存 if (options.extra['list']) { //若是列表,则只要url中包含当前path的缓存全部删除(简单实现,并不精准) cache.removeWhere((key, value) => key.contains(options.path)); } else { // 如果不是列表,则只删除uri相同的缓存 cacheDelete(options.uri.toString()); } // 删除磁盘缓存 if (cacheDisk) { StorageService.to.remove(options.uri.toString()); } } // get 请求,开启缓存 if (options.extra['noCache'] != true && options.method.toLowerCase() == "get") { String key = options.extra['cacheKey'] ?? options.uri.toString(); // 策略 1 内存缓存优先,2 然后才是磁盘缓存 var ob = cache[key]; // 1 内存缓存 if (ob != null) { //若缓存未过期,则返回缓存内容 if ((DateTime.now().millisecondsSinceEpoch - ob.timestamp) / 1000 < CacheMaxAge) { CacheObject? cacheRes = cache[key]; if (cacheRes != null) { // print('命中内存缓存: $key'); handler.resolve(cacheRes.response); return; } } else { //若已过期则删除缓存,继续向服务器请求 cacheDelete(key); } } // 2 磁盘缓存 if (cacheDisk) { var cacheData = StorageService.to.getJSON(key); if (cacheData != null) { // 若缓存未过期,则返回缓存内容 if ((DateTime.now().millisecondsSinceEpoch - cacheData['timestamp']) / 1000 < DiskCacheMaxAge) { handler.resolve( Response( requestOptions: options, statusCode: 200, data: cacheData['data'], ), ); return; } else { //若已过期则删除缓存,继续向服务器请求 StorageService.to.remove(key); } } } } super.onRequest(options, handler); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { // 将返回结果保存到缓存 _setCache(response); super.onResponse(response, handler); } _setCache(Response response) { RequestOptions options = response.requestOptions; // 只缓存 get 的请求 if (options.extra["noCache"] != true && options.method.toLowerCase() == "get") { // 如果缓存数量超过最大数量限制,则先移除最早的一条记录 if (cache.length >= CacheMaxCount) { cacheDelete(cache.keys.first); } // 策略:内存、磁盘都写缓存 String key = options.extra['cacheKey'] ?? options.uri.toString(); // 磁盘缓存 if (options.extra["cacheDisk"] == true) { final diskData = { "timestamp": DateTime.now().millisecondsSinceEpoch, "data": response.data, }; StorageService.to.setJSON(key, diskData); } // 内存缓存 cache[key] = CacheObject(response); } } void cacheDelete(String key) { cache.remove(key); } }