Hymanme

XUtils3.0 解决不缓存问题

xutils3.0是一次彻底的重构, api发生了很大变化, 但是仍然保持着xUtils一贯的简介风格, 并且新的api更加简单, 更具扩展性。参考sample写的案例发现不走缓存(onCache)。原因可能为以下两种:

1. 未设置缓存
2. 接口返回头expires设置过期时间为过去时间(即不缓存)


1. 未设置缓存

通过调用 setCacheMaxAge()设置缓存时间,单位毫秒

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
BaiduParams params = new BaiduParams();
params.wd = "xUtils";
// 默认缓存存活时间, 单位:毫秒.(如果服务没有返回有效的max-age或Expires)
params.setCacheMaxAge(1000 * 60);
Callback.Cancelable cancelable
// 使用CacheCallback, xUtils将为该请求缓存数据.
= x.http().get(params, new Callback.CacheCallback<String>() {
private boolean hasError = false;
private String result = null;
@Override
public boolean onCache(String result) {
// 得到缓存数据, 缓存过期后不会进入这个方法.
// 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法.
//
// * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法.
// 如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的
// 逻辑, 那么xUtils将请求新数据, 来覆盖它.
//
// * 如果信任该缓存返回 true, 将不再请求网络;
// 返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息,
// 如果服务端返回304, 则表示数据没有更新, 不继续加载数据.
//
this.result = result;
return false; // true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据.
}
@Override
public void onSuccess(String result) {
// 注意: 如果服务返回304或 onCache 选择了信任缓存, 这里将不会被调用,
// 但是 onFinished 总会被调用.
this.result = result;
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
hasError = true;
Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
if (ex instanceof HttpException) { // 网络错误
HttpException httpEx = (HttpException) ex;
int responseCode = httpEx.getCode();
String responseMsg = httpEx.getMessage();
String errorResult = httpEx.getResult();
// ...
} else { // 其他错误
// ...
}
}
@Override
public void onCancelled(CancelledException cex) {
Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
}
@Override
public void onFinished() {
if (!hasError && result != null) {
// 成功获取数据
Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
}
}
});

2. 接口返回头expires设置过期时间为过去时间(即不缓存)

在使用注解模板时,可以在responseParser里面手动缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class JsonResponseParser implements ResponseParser {
private UriRequest request;
@Override
public void checkResponse(UriRequest request) throws Throwable {
//请求网络时候走这里
this.request = request;
}
@Override
public Object parse(Type resultType, Class<?> resultClass, String result) throws Throwable {
//解析,缓存先走这里,如果缓存没有找到或者未设置缓存,那么再走checkResponse
//如果服务器接口返回缓存过期时间为过去时间(即不缓存)那么手动设置过期时间为
//System.currentTimeMillis() + request.getParams().getCacheMaxAge()
if (request != null && !TextUtils.isEmpty(result) && request.getExpiration() < System.currentTimeMillis()) {
DiskCacheEntity entity = new DiskCacheEntity();
entity.setKey(request.getCacheKey());
entity.setLastAccess(System.currentTimeMillis());
entity.setEtag(request.getETag());
// entity.setExpires(request.getExpiration());
entity.setExpires(System.currentTimeMillis() + request.getParams().getCacheMaxAge());
entity.setLastModify(new Date(request.getLastModified()));
entity.setTextContent(result);
LruDiskCache.getDiskCache(request.getParams().getCacheDirName()).put(entity);
}
if (resultClass == List.class) {
// fastJson 解析:
return JSON.parseArray(result, (Class<?>) ParameterizedTypeUtil.getParameterizedType(resultType, List.class, 0));
} else {
// fastjson 解析:
return JSON.parseObject(result, resultClass);
}
}
}

感谢wyouflf的帮助