news_getx/lib/utils/net_cache.dart

139 lines
4.2 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}