OkHttp 可以对 HTTP 响应的内容在磁盘上进行缓存。在进行 HTTP 请求时,如果该请求的响应已经被缓存而且没有过期,OkHttp 会直接使用缓存中的响应内容,而不需要真正的发出 HTTP 请求到远程服务器。在创建缓存时需要指定一个磁盘目录和缓存的大小。在代码清单 8 中,创建出 Cache 对象之后,通过 OkHttpClient 的 setCache 进行设置。通过 Response 对象的 cacheResponse 和 networkResponse 方法可以得到缓存的响应和从实际的 HTTP 请求得到的响应。如果该请求的响应来自实际的网络请求,则 cacheResponse 方法的返回值为 null;如果响应来自缓存,则 networkResponse 的返回值为 null。OkHttp 在进行缓存时会遵循 HTTP 协议的要求,因此可以通过标准的 HTTP 头 Cache-Control 来控制响应的缓存时间。
设置响应缓存的示例
public class CacheResponse { public static void main(String[] args) throws IOException { int cacheSize = 100 * 1024 * 1024; File cacheDirectory = Files.createTempDirectory("cache").toFile(); Cache cache = new Cache(cacheDirectory, cacheSize); OkHttpClient client = new OkHttpClient(); client.setCache(cache); Request request = new Request.Builder() .url("http://www.baidu.com") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("服务器端错误: " + response); } System.out.println(response.cacheResponse()); System.out.println(response.networkResponse()); } }
Cache-Control
Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令有下几种:
Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
(1)no-cache指示请求或响应消息不能缓存
(2)no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
(3)max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
(4)min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
(5)max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
CacheControl类详细介绍:
1.)常用的函数:如下代码,里面已经加了注释就不一一解释了,每个函数都是对应一个缓存指令设置
final CacheControl.Builder builder = new CacheControl.Builder(); builder.noCache();//不使用缓存,全部走网络 builder.noStore();//不使用缓存,也不存储缓存 builder.onlyIfCached();//只使用缓存 builder.noTransform();//禁止转码 builder.maxAge(10, TimeUnit.MILLISECONDS);//指示客户机可以接收生存期不大于指定时间的响应。 builder.maxStale(10, TimeUnit.SECONDS);//指示客户机可以接收超出超时期间的响应消息 builder.minFresh(10, TimeUnit.SECONDS);//指示客户机可以接收响应时间小于当前时间加上指定时间的响应。 CacheControl cache = builder.build();//cacheControl
2.)两个CacheControl常量介绍:
CacheControl.FORCE_CACHE; //仅仅使用缓存 CacheControl.FORCE_NETWORK;// 仅仅使用网络
举例,我们设置一个有效期为10秒的CacheControl
final CacheControl.Builder builder = new CacheControl.Builder(); builder.maxAge(10, TimeUnit.MILLISECONDS); CacheControl cache = builder.build();
3.)请求时如何使用
final CacheControl.Builder builder = new CacheControl.Builder(); builder.maxAge(10, TimeUnit.MILLISECONDS); CacheControl cache = builder.build(); final Request request = new Request.Builder().cacheControl(cache).url(requestUrl).build(); final Call call = mOkHttpClient.newCall(request);// call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { failedCallBack("访问失败", callBack); Log.e(TAG, e.toString()); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String string = response.body().string(); Log.e(TAG, "response ----->" + string); successCallBack((T) string, callBack); } else { failedCallBack("服务器错误", callBack); } } }); return call; } catch (Exception e) { Log.e(TAG, e.toString()); }
以上如果cache没有过去会直接返回cache而不会发起网络请求,若过期会自动发起网络请求。注意:如果您使用FORCE_CACHE和网络的响应需求,OkHttp则会返回一个504提示,告诉你不可满足请求响应。所以我们加一个判断在没有网络的情况下使用
//判断网络是否连接 boolean connected = NetworkUtil.isConnected(context); if (!connected) { request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build(); }