OKHTTP源码分析(二)同步方法以及拦截器链

来源:互联网 发布:淘宝客推广专区在哪里 编辑:程序博客网 时间:2024/05/29 03:44

         前一章我们分析了OKHTTP处理异步方法,这一章我们来分析一下OKHttp处理同步方法。

         同步方法调用的是Realcall的execute方法

@Override public Response execute() throws IOException {    synchronized (this) {      if (executed) throw new IllegalStateException("Already Executed");      executed = true;    }    captureCallStackTrace();    try {      client.dispatcher().executed(this);      Response result = getResponseWithInterceptorChain();      if (result == null) throw new IOException("Canceled");      return result;    } finally {      client.dispatcher().finished(this);    }  }
          RealCall方法先调用Dispatcher的executed方法 ,Dispatcher执行的只是将call加入runningSyncCalls(运行中的同步队列)。之后会调用getResponseWithInterceptorChain()方法,我们先不看getResponseWithInterceptorChain()方法,我们先跳到异步任务执行中, 异步任务的执行是在AsycCall的execute中

@Override protected void execute() {      boolean signalledCallback = false;      try {        Response response = getResponseWithInterceptorChain();        if (retryAndFollowUpInterceptor.isCanceled()) {          signalledCallback = true;          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));        } else {          signalledCallback = true;          responseCallback.onResponse(RealCall.this, response);        }      } catch (IOException e) {        if (signalledCallback) {          // Do not signal the callback twice!          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);        } else {          responseCallback.onFailure(RealCall.this, e);        }      } finally {        client.dispatcher().finished(this);      }    }

     可以看到不管是RealCall的execute方法还是AsycCall的execute方法,都执行了getResponseWithInterceptorCharin(),可见这个方法很重要哈!这个方法构建了okhttp的拦截器链,okhttp的重连,缓存等重要特性,都是通过一个个的拦截器来完成的,辣磨我们来看一看getResponseWithInterceptorChain()方法吧

 

Response getResponseWithInterceptorChain() throws IOException {    // Build a full stack of interceptors.    List<Interceptor> interceptors = new ArrayList<>();    interceptors.addAll(client.interceptors());    interceptors.add(retryAndFollowUpInterceptor);    interceptors.add(new BridgeInterceptor(client.cookieJar()));    interceptors.add(new CacheInterceptor(client.internalCache()));    interceptors.add(new ConnectInterceptor(client));    if (!forWebSocket) {      interceptors.addAll(client.networkInterceptors());    }    interceptors.add(new CallServerInterceptor(forWebSocket));    Interceptor.Chain chain = new  Response getResponseWithInterceptorChain() throws IOException {    // Build a full stack of interceptors.    List<Interceptor> interceptors = new ArrayList<>();    interceptors.addAll(client.interceptors());    interceptors.add(retryAndFollowUpInterceptor);    interceptors.add(new BridgeInterceptor(client.cookieJar()));    interceptors.add(new CacheInterceptor(client.internalCache()));    interceptors.add(new ConnectInterceptor(client));    if (!forWebSocket) {      interceptors.addAll(client.networkInterceptors());    }    interceptors.add(new CallServerInterceptor(forWebSocket));    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,        originalRequest, this, eventListener, client.readTimeoutMillis(),        client.writeTimeoutMillis());    return chain.proceed(originalRequest);  }}(interceptors, null, null, null, 0,        originalRequest, this, eventListener, client.readTimeoutMillis(),        client.writeTimeoutMillis());    return chain.proceed(originalRequest);  }}


     从上面的代码可以看出getResponseWithInterceptor先将拦截器加入拦截器数组,然后构建拦截器链  RealInterceptorChain    ,并返回RealInterceptorChain.proceed()


public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,      RealConnection connection) throws IOException {    if (index >= interceptors.size()) throw new AssertionError();    calls++;    // If we already have a stream, confirm that the incoming request will use it.    if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)          + " must retain the same host and port");    }    // If we already have a stream, confirm that this is the only call to chain.proceed().    if (this.httpCodec != null && calls > 1) {      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)          + " must call proceed() exactly once");    }    // Call the next interceptor in the chain.    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,        connection, index + 1, request, call, eventListener, readTimeout, writeTimeout);    Interceptor interceptor = interceptors.get(index);    Response response = interceptor.intercept(next);    // Confirm that the next interceptor made its required call to chain.proceed().    if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {      throw new IllegalStateException("network interceptor " + interceptor          + " must call proceed() exactly once");    }    // Confirm that the intercepted response isn't null.    if (response == null) {      throw new NullPointerException("interceptor " + interceptor + " returned null");    }    if (response.body() == null) {      throw new IllegalStateException(          "interceptor " + interceptor + " returned a response with no body");    }    return response;  }} 


上面的核心逻辑是构建next 拦截器链,然后执行拦截器的intercept方法,将next链传递给intercept方法,intercept方法会返回response。过程相当于执行拦截器链中每一个拦截器的intercept方法,然后每个拦截器返回response,最终构建成真正需要返回的Response.

  最后 调用Dispatcher.finished方法,将执行结束的任务从任务队列中删除。

    总结:不管是同步方法还是异步方法,最终都会构建拦截器链,拦截器链中构建拦截器数组,并且递归执行拦截器的拦截方法,并返回最终的Response.


阅读全文
0 0
原创粉丝点击