您的位置 首页 > 数码极客

okhttp如何设置缓存

本文基于compile 'com.;

OkHttp的时序图

1.基本用法


这里我是将Okhttp和Retrofit一起使用的

Okhttp执行底层的网络请求,Retrofit负责网络调度,有关Retrofit的更多可参考我的另一篇博文:Retrofit基本用法和流程分析

1.初始化

public static void init() {

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

logging.setLevel);

sClient = new OkH()

.retryOnConnectionFailure(true)

.connectTimeout(15, TimeUnit.SECONDS)

.readTimeout(300, TimeUnit.SECONDS)

.writeTimeout(300, TimeUnit.SECONDS)

.cache(new Cache, Con))

.addinterceptor(logging)//第三方的日志拦截器

.addInterceptor(appIntercepter)//自定义的应用拦截器

.addNetworkInterceptor(netIntercepter)//自定义的网络拦截器

.build();

}

2.添加应用拦截器

//应用拦截器:主要用于设置公共参数,头信息,日志拦截等,有点类似Retrofit的Converter private static Interceptor appIntercepter = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { request Request = processReque()); Response response = processResponse(request)); return response; } }; //访问网络之前,处理Request(这里统一添加了Cookie) private static Request processRequest(Request request) { String session = Cac()).getSession(); return request .newBuilder() .addheader("Cookie", "JSESSIONID=" + session) .build(); } //访问网络之后,处理Response(这里没有做特别处理) private static Response processResponse(Response response) { return response; }

这里再奉上一个缓存拦截器:离线读取本地缓存,在线获取最新数据(读取单个请求的请求头,亦可统一设置)。

这里用到了一个网络状态工具类

//应用拦截器:设置缓存策略 private static Interceptor cacheIntercepter = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = c(); //无网的时候强制使用缓存 if () == Ne) { request = reque() .cacheControl) .build(); } Response response = c(request); //有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置 if () != Ne) { String cacheControl = reque().toString(); return re() .header("Cache-Control", cacheControl) .removeHeader("Pragma") .build(); } else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale return re() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .removeHeader("Pragma") .build(); } } };

OkHttp3中有一个Cache类是用来定义缓存的,此类详细介绍了几种缓存策略,具体可看此类源码。

  • noCache :不使用缓存,全部走网络
  1. noStore : 不使用缓存,也不存储缓存
  2. onlyIfCached : 只使用缓存
  3. maxAge :设置最大失效时间,失效则不使用
  4. maxStale :设置最大失效时间,失效则不使用
  5. minFresh :设置最小有效时间,失效则不使用
  6. FORCE_NETWORK : 强制走网络
  7. FORCE_CACHE :强制走缓存

关于max-age和max-stale

max-stale在请求头设置有效,在响应头设置无效。

max-stale和max-age同时设置的时候,缓存失效的时间按最长的算。

我这里借用了别人的一个测试(太懒了,你有兴趣可以自己测试下):

测试结果:

在请求头中设置了:Cache-Control: public, max-age=60,max-stale=120,响应头的Cache-Control和请求头一样。

  1. 在第一次请求数据到一分钟之内,响应头有:Cache-Control: public, max-age=60,max-stale=120
  2. 在1分钟到3分钟在之间,响应头有:Cache-Control: public, max-age=60,max-stale=120
  3. Warning: 110 HttpURLConnection "Response is stale"
  4. 可以发现多了一个Warning。
  5. 三分钟的时候:重新请求了数据,如此循环,如果到了重新请求的节点此时没有网,则请求失败。
  6. 另外关于缓存有一个rxcache也可以试试。

3.添加网络拦截器

//网络拦截器:主要用于重试或重写 private static Interceptor netIntercepter = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = c(); Response response = c(request); int tryCount = 0; while (!re() && tryCount < sMaxTryCount) { tryCount++; response = c(request); } return response; } };

关于OkHttp的拦截机制,我觉得这是OkHttp最牛逼的地方之一!

先给大家看个概览图,之后会在OkHttp的特性中详细介绍下。

OkHttp的拦截机制

4.简单的异步请求

private static void testAsync() { Request request = new Reque() .url(";) .build(); (request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { LogU()); } @Override public void onResponse(Call call, Response response) throws IOException { if (!re()) throw new IOException("Unexpected code " + response); Headers responseHeaders = re(); for (int i = 0, size = re(); i < size; i++) { LogU(i) + ": " + re(i)); } LogU().string()); } }); }

2.OkHttp的特性


Q1:为什么使用OkHttp?

  • 支持HTTP2/SPDY黑科技
  1. socket自动选择最好路线,并支持自动重连
  2. 拥有自动维护的socket连接池,减少握手次数
  3. 拥有队列线程池,轻松写并发
  4. 拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
  5. 基于Headers的缓存策略

Q2:应用拦截器和网络拦截器的区别?

addInterceptor:设置应用拦截器,主要用于设置公共参数,头信息,日志拦截等

addNetworkInterceptor:设置网络拦截器,主要用于重试或重写

OkHttp的应用拦截器和网络拦截器

例如:初始请求 会重定向1次到 。

则应用拦截器会执行1次,返回的是https的响应

网络拦截器会执行2次,第一次返回http的响应,第二次返回https的响应

应用拦截器:

  1. 不需要担心中间过程的响应,如重定向和重试.
  2. 总是只调用一次,即使HTTP响应是从缓存中获取.
  3. 观察应用程序的初衷. 不关心OkHttp注入的头信息如: If-None-Match.
  4. 允许短路而不调用 C(),即中止调用.
  5. 允许重试,使 C()调用多次.

网络拦截器

  1. 能够操作中间过程的响应,如重定向和重试.
  2. 当网络短路而返回缓存响应时不被调用.
  3. 只观察在网络上传输的数据.
  4. 携带请求来访问连接.

3.OkHttp的流程分析


二话不说,先上几张图:

OkHttp的请求流程

OkHttp的总体设计

1.先看初始化时,通过建造者模式创建OkHttpClient

2.再看执行请求时,创建Request的方法

3.再看异步请求Request的方法,先通过newCall(),将Request转成Call

4.然后加入请求队列

5.Call.enqueue()是抽象方法,实现在这:

6.调用了Di(),通过一个线程池来执行,超过最大请求数后则先加入准备请求的队列中

7.这里的call是一个AsynCall,继承自NamedRunnable

8.在NamedRunnable的run()方法中,调用了execute()抽象方法,于是我们去找它的实现类AsyncCall的execute()方法

9.调用了getResponseWithInterceptorChain()方法

10.调用了ApplicationInterceptorC(),如果有其他的应用拦截器的话,就会遍历拦截器集合,执行每一个拦截的intercept()方法

而通过前面的自定义应用拦截器,我们知道intercept()中其实也会调用proceed(),这样迭代多次后,最终还是会执行getResponse方法()

13.getResponse()这个方法有点长,一次截图截不完

14.调用()方法,这个方法有点长,一次截图截不完

15.先从 Cache 中判断当前请求是否可以从缓存中返回

16.没有Cache则连接网络

17.调用()

18.寻找可用的socket连接

19.连接到socket连接层

20.创建了FramedConnection的实例

21.调用了Reader的execute()

写在最后:

码字不易看到最后了,那就点个关注呗,只收藏不点关注的都是在耍流氓!

关注并私信我“架构”,免费送一些Java架构资料,先到先得!记得转发哦!

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“okhttp如何设置缓存”边界阅读