139 lines
4.2 KiB
Dart
139 lines
4.2 KiB
Dart
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 = <String, CacheObject>{};
|
||
|
||
@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 = <String, dynamic>{
|
||
"timestamp": DateTime.now().millisecondsSinceEpoch,
|
||
"data": response.data,
|
||
};
|
||
StorageService.to.setJSON(key, diskData);
|
||
}
|
||
// 内存缓存
|
||
cache[key] = CacheObject(response);
|
||
}
|
||
}
|
||
|
||
void cacheDelete(String key) {
|
||
cache.remove(key);
|
||
}
|
||
}
|