OkHttp源码解析

参考:

源码版本:3.14.9
源码地址:https://github.com/square/okhttp

此篇文章主要讲解OkHttp的请求过程,以及源码中一些比较难懂的知识点的使用,并把这些知识点抽取成一个Demo,可以比较深刻的去理解源码的执行过程。Demo 包含 :

  1. 源码中 Dispatcher类的调度过程
  2. 以及RealCall类中getResponseWithInterceptorChain()方法中责任链模式的调度过程。
image.png

简单调用

       String url = "www.baidu.com";
       OkHttpClient client = new OkHttpClient.Builder().build();
       Request request = new Request.Builder().url(url).build();

       Call call = client.newCall(request);
       call.enqueue(new Callback() {
           @Override
           public void onFailure(Call call, IOException e) {

           }

           @Override
           public void onResponse(Call call, Response response) throws IOException {

           }
       });

源码解析流程

此处不讲解OkHttpClient的初始化过程,以及Request的构建过程,用到的是 Builder设计模式,直接从enqueue()方法开始解析。

1. 请求发送过程

  • 注意:call.execute()是同步方法,call.enqueue()是异步方法,一般调用call.enqueue()

点击查看call.enqueue()方法,进入到 RealCall类中的call.enqueue()方法,如下:

  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.callStart();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

这个 RealCall里面执行的方法,首先会把这个Call加入到Dispatcher这个调度器里面,进入Dispatcher类中的 enqueue() 方法,如下:

void enqueue(AsyncCall call) {
  synchronized (this) {
    //将此次请求加入准备请求队列中
    readyAsyncCalls.add(call);

    // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
    // the same host.
    if (!call.get().forWebSocket) {
      AsyncCall existingCall = findExistingCallWithHost(call.host());
      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
    }
  }
  promoteAndExecute();
}

Dispatcher类中包含了三个队列,一个线程池:
为了管理所有的请求,Dispatcher采用了队列+生产+消费的模式。

  • 为同步执行提供了runningSyncCalls来管理所有的同步请求;
  • 为异步执行提供了runningAsyncCalls和readyAsyncCalls来管理所有的异步请求。其中readyAsyncCalls是在当前可用资源不足时,用于缓存请求的。
  • ExecutorService线程池

查看 promoteAndExecute()方法,

  private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();

        if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.

        i.remove();
        asyncCall.callsPerHost().incrementAndGet();
        executableCalls.add(asyncCall);
        runningAsyncCalls.add(asyncCall);
      }
      isRunning = runningCallsCount() > 0;
    }

    for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
    //调用 AsyncCall 类 executeOn的方法,在executeOn方法中开启线程池
      asyncCall.executeOn(executorService());//1
    }

    return isRunning;
  }

在1处会调用AsyncCall中的executeOn()方法

    void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
        executorService.execute(this);//开启线程池
        success = true;
      } catch (RejectedExecutionException e) {
        InterruptedIOException ioException = new InterruptedIOException("executor rejected");
        ioException.initCause(e);
        transmitter.noMoreExchanges(ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

此时会调用AsyncCall中的execute()方法,

    @Override protected void execute() {
      boolean signalledCallback = false;
      transmitter.timeoutEnter();
      try {
        //核心函数
        Response response = getResponseWithInterceptorChain();
        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);
        }
      } catch (Throwable t) {
        cancel();
        if (!signalledCallback) {
          IOException canceledException = new IOException("canceled due to " + t);
          canceledException.addSuppressed(t);
          responseCallback.onFailure(RealCall.this, canceledException);
        }
        throw t;
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

getResponseWithInterceptorChain()方法就是执行拦截器链,直到返回 Response。通过责任链模式循环调用所有拦截器,每个拦截器可以根据Request和Reponse前后执行相应的逻辑。

  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(new RetryAndFollowUpInterceptor(client));
    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, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    boolean calledNoMoreExchanges = false;
    try {
      Response response = chain.proceed(originalRequest);
      if (transmitter.isCanceled()) {
        closeQuietly(response);
        throw new IOException("Canceled");
      }
      return response;
    } catch (IOException e) {
      calledNoMoreExchanges = true;
      throw transmitter.noMoreExchanges(e);
    } finally {
      if (!calledNoMoreExchanges) {
        transmitter.noMoreExchanges(null);
      }
    }
  }

这里把自定义的拦截器,还有内置的必要的拦截器都添加到一个List里面了,最后用List的拦截器创建一个拦截器的链—— RealInterceptorChain。而这个RealInterceptorChain 其实是实现了Interceptor 里面的一个Chain 接口。

我们先了解一下RealInterceptorChain 这个类是如何进行工作的。

首先RealInterceptorChain,是实现了Interceptor.Chain 接口的一个类,这个接口有是三个方法,后面会介绍到,其中一个就是前面调用的proceed方法。

public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
      throws IOException {
      ...
    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

    return response;
  }

省略了前后的一些代码,发现,其实这里又新建一个 RealInterceptorChain,然后调用了这个拦截器的 intercept 的方法。那么在每个拦截器里面做了什么,这个拦截的方法又是做了什么呢?

首先看一下拦截器这个接口:

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;
    ...
  }
}

很明显,每个实现Interceptor的拦截器。都会实现了intercept,这样一个拦截的方法。而传入的就是一个Chain。符合前面RealInterceptorChain的调用。

以一个拦截器的代码为例:BridgeInterceptor,这个类实现的intercept方法,而这个方法里面,除了那些前置或后续的操作之外,在中间你会发现 下面一句代码:

Response networkResponse = chain.proceed(requestBuilder.build());

又通过传进来的Chain ,重新调用了proceed的方法。好吧,到这里应该可以了解到这些拦截器,是如何一个个调用被调用的了,原理都是通过了中间的一个RealInterceptorChain,一个接一个的向下调用。然后得到的结果又一个一个向上传。

总结一下,这些拦截器的调用:

刚开始getResponseWithInterceptorChain的最后开始调用了 chain.proceed,然后在RealInterceptorChain的里面,又新建一个 RealInterceptorChain,并且调用当前的拦截器的 intercept,并且把新建的Chain传递进去,然后拦截器的 intercept方法里面,除了一些自身的操作外,又调用Chain的proceed方法。就这样一直调用新建Chian, 一直调用到最后一个拦截器。

这里的调用其实是一个迭代,递归的结构。请求做了前一步的处理才能到下一级,一级级下去,到最后真正发出去请求,相对做了拦截。而得到结果,只有当最后一个拦截器完全了请求,拿到结果之后,才会把结果往上一级,上一级拿到结果,做了相应的处理之后,再到上一级,这就是对结果的拦截处理。

Demo

结构:

image.png

调用:

    public static void main(String[] args) throws IOException {
        //Dispatcher类的调度过程
        new Dispatcher().enqueue(new AsyncCall("22","33"));

        //demo02调用RealCall类中getResponseWithInterceptorChain()
        //方法中责任链模式的调度过程
        Request request = new Request();
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.add(new RetryAndFollowUpInterceptor());
        interceptors.add(new BridgeInterceptor());
        interceptors.add(new CacheInterceptor());
        interceptors.add(new ConnectInterceptor());

        Interceptor.Chain chain = new RealInterceptorChain(interceptors,0,request);

        Response response = chain.proceed(request);
    }

运行结果:

---Dispatcher---enqueue-
--AsyncCall执行execute方法--
1.失败重试拦截器
2.请求和响应转换拦截器
3.缓存拦截器
4.与服务器建立连接拦截器
 RealInterceptorChain 第 3 次执行
 RealInterceptorChain 第 2 次执行
 RealInterceptorChain 第 1 次执行
 RealInterceptorChain 第 0 次执行

Demo挺简单的,可以自行下载:
https://github.com/Ityang/OKHttpDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。