okHttp 源码解析-四 缓存拦截器 CacheInterceptor

缓存拦截器就是处理缓存数据,这个思路上不复杂,如果你们配置使用缓存数据,就会根据缓存策略判断是否能使用缓存的数据,如果可以就取缓存的数据,否则,则去请求网络。

  @Override public Response intercept(Chain chain) throws IOException {
 /** 首先判断缓存对象是否为null,非空就获取缓存对象,否则null,且给Response 赋值
  *cache对象是谁, InternalCache cache; 由当前缓存拦截器构造的时候传入。*InternalCache 是个接口,所以去看实现类,但是实现类没有,但是在okhttp3.Cache里找
  *到了InternalCache 的内部类实例,同时还重写相应的方法。get put remove update等方法。
  下面细讲
  */
    Response cacheCandidate = cache != null ? cache.get(chain.request())  : null;

    long now = System.currentTimeMillis();
//CacheStrategy 缓存策略对象,工厂模式,最后get()获取
    CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
    Request networkRequest = strategy.networkRequest;
    Response cacheResponse = strategy.cacheResponse;

    if (cache != null) {
      cache.trackResponse(strategy);
    }

//缓存对象不为空,但是缓存的响应对象null,关闭缓存
    if (cacheCandidate != null && cacheResponse == null) {
      closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
    }

    // If we're forbidden from using the network and the cache is insufficient, fail.
    // 网络请求对象null 缓存对象null 直接返回504 服务器错误
    if (networkRequest == null && cacheResponse == null) {
      return new Response.Builder()
          .request(chain.request())
          .protocol(Protocol.HTTP_1_1)
          .code(504)
          .message("Unsatisfiable Request (only-if-cached)")
          .body(Util.EMPTY_RESPONSE)
          .sentRequestAtMillis(-1L)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();
    }

    // If we don't need the network, we're done.
    // 请求对象为null,返回缓存的对象,该对象是null的body对象,
    //stripBody方法去除了body
    if (networkRequest == null) {
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }

    Response networkResponse = null;
    try {
    // 执行下一个拦截器
      networkResponse = chain.proceed(networkRequest);
    } finally {
      // If we're crashing on I/O or otherwise, don't leak the cache body.
      if (networkResponse == null && cacheCandidate != null) {
//      	关闭缓存
        closeQuietly(cacheCandidate.body());
      }
    }

    // If we have a cache response too, then we're doing a conditional get.
//    如果缓存对象不为空,且返回403-重定向无修改数据,合并缓存的header和网络的header
//
    if (cacheResponse != null) {
      if (networkResponse.code() == HTTP_NOT_MODIFIED) {
        Response response = cacheResponse.newBuilder()
            .headers(combine(cacheResponse.headers(), networkResponse.headers()))
            .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
            .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
            .cacheResponse(stripBody(cacheResponse))
            .networkResponse(stripBody(networkResponse))
            .build();
        networkResponse.body().close();

        // Update the cache after combining headers but before stripping the
        // Content-Encoding header (as performed by initContentStream()).
        cache.trackConditionalCacheHit();
        //更新缓存数据
        cache.update(cacheResponse, response);
        return response;
      } else {
        closeQuietly(cacheResponse.body());
      }
    }
	
    Response response = networkResponse.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build();
	// 判断是否有body
    if (HttpHeaders.hasBody(response)) {
    	// 判断是否请求方法合法,因为缓存只处理GET请求,不合法从缓存对象移除
      CacheRequest cacheRequest = maybeCache(response, networkResponse.request(), cache);
      // 写入响应对象到缓存
      response = cacheWritingResponse(cacheRequest, response);
    }

    return response;
  }

CacheInterceptor

ConnectInterceptor

CallServerInterceptor

发布了58 篇原创文章 · 获赞 1 · 访问量 6872

猜你喜欢

转载自blog.csdn.net/chentaishan/article/details/103040796
今日推荐