转载务必注明出处:http://blog.csdn.net/u014614038/article/details/51210685
使用方法很简单:
private static final OkHttpClient client;
private static final long cacheSize = 1024 * 1024 * 20;// 缓存文件最大限制大小20M
private static String cacheDirectory = Environment.getExternalStorageDirectory() + "/okttpcaches"; // 设置缓存文件路径
private static Cache cache = new Cache(new File(cacheDirectory), cacheSize); //
static {
//如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(8, TimeUnit.SECONDS); // 设置连接超时时间
builder.writeTimeout(8, TimeUnit.SECONDS);// 设置写入超时时间
builder.readTimeout(8, TimeUnit.SECONDS);// 设置读取数据超时时间
builder.retryOnConnectionFailure(true);// 设置进行连接失败重试
builder.cache(cache);// 设置缓存
client = builder.build();
}
一般来说的是,我们get请求有时有不一样的需求,有时需要进行缓存,有时需要直接从网络获取,有时只获取缓存数据,这些处理,okhttp都有帮我们做了,我们做的只需要设置就是了。下面是整理的各种需求的设置与使用方法。
/** 如果没有缓存,进行get请求获取服务器数据并缓存起来
* 如果缓存已经存在:不超过maxAge---->不进行请求,直接返回缓存数据
* 超出了maxAge--->发起请求获取数据更新,请求失败返回旧的缓存数据
* @param url
* @param cache_maxAge_inSeconds
* @param responseListener
* @return
*/
public static Call DoGetAndCache(String url, int cache_maxAge_inSeconds,
final NetWorkResponseListener responseListener) {
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder().maxAge(cache_maxAge_inSeconds, TimeUnit.SECONDS)
.build())
.url(url).build();
Call call = client.newCall(request);
startRequest(call, responseListener);
return call;
}
/** 如果没有缓存,进行get请求获取服务器数据并缓存起来
* 如果缓存已经存在:不超过maxStale---->不进行请求,直接返回缓存数据
* 超出了maxStale--->发起请求获取数据更新,请求失败返回失败
* @param url
* @param cache_maxStale_inSeconds
* @param responseListener
* @return
*/
public static Call DoGetAndCacheInStaleTime(String url, int cache_maxStale_inSeconds,
final NetWorkResponseListener responseListener) {
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder().maxStale(cache_maxStale_inSeconds, TimeUnit.SECONDS)
.build())
.url(url).build();
Call call = client.newCall(request);
startRequest(call, responseListener);
return call;
}
/**
* get请求,只获取网络数据
*
* @param url
* @param responseListener
* @return
*/
public static Call DoGetOnlyNet(String url, final NetWorkResponseListener responseListener) {
Request request = new Request.Builder().cacheControl( CacheControl.FORCE_NETWORK).url(url)
.build();
Call call = client.newCall(request);
startRequest(call, responseListener);
return call;
}
/**
* get请求, 只使用缓存,注意,如果没有缓存数据,返回504,否则就返回缓存数据,不管缓存数据是否超出max-age与max-stale
*
* @param url
* @param responseListener
*/
public static Call DoGetOnlyCache(String url, final NetWorkResponseListener responseListener) {
Request request = new Request.Builder().cacheControl( CacheControl.FORCE_CACHE).url(url)
.build();
Call call = client.newCall(request);
startRequest(call, responseListener);
return call;
}
private static void startRequest(final Call call0,
final NetWorkResponseListener responseListener) {
try {
call0.enqueue(new Callback() {
@Override
public void onFailure(Call arg0, IOException arg1) {
String message = "未知错误";
if (arg1 != null) {
Throwable t = arg1.getCause();
message = arg1.toString();
if (t != null) {
if (t instanceof SocketTimeoutException) {
message = "请求超时了";
} else if (t instanceof UnknownHostException) {
message = "UnknownHostException,无法访问该地址";
}
}
}
responseListener.onFail(message);
}
@Override
public void onResponse(Call arg0, Response response) throws IOException {
if (response.isSuccessful()) {
responseListener.onSuccess(response.body().string() + "");
} else {
if(response.cacheResponse()!=null){
responseListener.onSuccess(response.cacheResponse().body().string() + "");
}else {
responseListener.onFail("response失败了,连接状态码为:" + response.code());
}
}
}
});
} catch (Exception e) {
responseListener.onFail("请求异常:" + e.toString());
}
}
下面测试一下,设置缓存maxStale为10秒,我们将请求返回的数据打印出来:
上面图片的1是点击获取的服务器的数据,获取后断开网络然后继续点击,可以看到2还能获取到数据,说明这是缓存的数据,当到3时,差不多就是十秒的时间,可以看到,获取数据失败了,这时已经去服务器获取数据了,由于断开网络所以请求失败。
可能出现的问题:
1.缓存文件没有生成。
只要配置成功,缓存目录一定会有的,所以看看:1.权限配置是否完整 2.手机应用权限是不是拒绝了。
可能是请求的服务器不支持配置返回maxAge等头数据,建议通过配置缓存拦截器去添加这些参数:
static {
//如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(8, TimeUnit.SECONDS); // 设置连接超时时间
builder.writeTimeout(8, TimeUnit.SECONDS);// 设置写入超时时间
builder.readTimeout(8, TimeUnit.SECONDS);// 设置读取数据超时时间
builder.retryOnConnectionFailure(true);// 设置进行连接失败重试
builder.cache(cache);// 设置缓存
builder.addNetworkInterceptor(new CacheInterceptor());//缓存拦截器,通过这个设置maxAge与maxStale
client = builder.build();
}
/**
* 缓存拦截器
*/
private static class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response originResponse = chain.proceed(chain.request());
//设置缓存时间为,并移除了pragma消息头,移除它的原因是因为pragma也是控制缓存的一个消息头属性
return originResponse.newBuilder().removeHeader("pragma")
.header("Cache-Control", "max-age=10")//设置10秒
.header("Cache-Control", "max-stale=30").build();
}
}
3.缓存返回总是返回504或者无法返回缓存数据,可是缓存文件又已经生成
如果get请求是带参数的话,可能参数值不同导致拼接的url地址不一样,会被认为是新地址去重新发起请求获取数据,当然被认为没有缓存数据
以上都是本人查看官方文档并进行测试验证后整理的,有不对的地方,万请指正。
封装了比较完整的网络请求工具类,包括请求相关信息的判断以及请求日志记录等,需要的可以看看:
点击进入