Okhttp3 源码流程梳理

首先OkHttp的应该都知道
以下为异步请求

OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .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 {

            }
        });

同步请求需要改动的也不多改调用enqueue为call.execute()
先来看看主要的三个类

  • Request和Response看名字就大概知道是代表什么
  • Call:封装已经准备好要执行的Request,可以同步和异步执行
    OkHttpClient可以调用Builder自定义一些配置,也可以采用默认配置。先来按照顺序梳理源码
    不调用Builder便会默认构建一个Builder
public OkHttpClient() {
    this(new Builder());
  }
public Builder() {
//包含了一些常见的参数,看名字应该知道什么含义了
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      if (proxySelector == null) {
        proxySelector = new NullProxySelector();
      }
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      callTimeout = 0;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }

再来看Request

//可以看到默认是采用GET请求
public Builder() {
      this.method = "GET";
      this.headers = new Headers.Builder();
    }

在接下来看client.newCall(request);该方法会返回一个Call对象,看到这里也印证了上面的Call是封装的要准备执行的Request对象,但是具体实现由RealCall完成

    return RealCall.newRealCall(this, request, false /* for web socket */);

再来看看Call接口里面具体的方法吧,去掉了无用的部分,是不是每个功能都很清晰

public interface Call extends Cloneable {

  Request request();

  Response execute() throws IOException;

  void enqueue(Callback responseCallback);

  void cancel();

  boolean isExecuted();

  boolean isCanceled();

  Timeout timeout();

  Call clone();
//这个方法是用于将Request封装为Call的Factory
  interface Factory {
    Call newCall(Request request);
  }
}

再顺着看enqueue方法,具体实现再RealCall中

@Override public void enqueue(Callback responseCallback) {
//如果重复执行直接抛出异常
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

client就是OkhttpClient实例,dispatcher()会返回Dispatcher对象的实例。接下来到DIspatcher

//最大请求数
  private int maxRequests = 64;
  //最大的请求主机数
  private int maxRequestsPerHost = 5;
  private @Nullable Runnable idleCallback;

  /** Executes calls. Created lazily. */
  private @Nullable ExecutorService executorService;

//准备异步执行的Call队列
  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
//正在异步执行的Call队列,包括在执行但是已被取消的Call
  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
//正在执行的同步队列,包括被取消Call
  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

最后调用到Dispatcher里的enqueue()方法, 先来看下AsyncCall是什么吧,其实大概也猜得到时用于异步执行的Call
果然是一个Runnable对象

final class AsyncCall extends NamedRunnable
//先加入准备执行异步任务队列,再调用promoteAndExecute()
  void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);
    }
    promoteAndExecute();
  }
  
  private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
    //将准备执行异步任务队列(readyAsyncCalls)中Call取出来加入到runningAsyncCalls中,同时放入executableCalls中方便次序执行
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();

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

        i.remove();
        executableCalls.add(asyncCall);
        runningAsyncCalls.add(asyncCall);
      }
      isRunning = runningCallsCount() > 0;
    }
//在线程池中执行具体AsyncCall
    for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
      asyncCall.executeOn(executorService());
    }

    return isRunning;
  }

会看到具体调用了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);
        eventListener.callFailed(RealCall.this, ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

线程池便会执行改Runnable的Run方法,上面已经说了AsyncCall继承自NamedRunnable

//说实话这名字取得真随意
public abstract class NamedRunnable implements Runnable {
  protected final String name;

  public NamedRunnable(String format, Object... args) {
    this.name = Util.format(format, args);
  }

  @Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
    //这里面调用excute方法,也就是AsyncCall里的
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();
}

接下来回到AsyncCall

protected void execute() {
      boolean signalledCallback = false;
      timeout.enter();
      try {
      //从拦截器链中获取response
        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) {
        e = timeoutExit(e);
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }

最后的Response通过层层拦截器获取

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    //可以看到把所有需要的拦截器都加入interceptors中了
    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));
//构造Chain对象,也就是整合所有的拦截器
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
//调用chain继续执行request,该方法的实现肯定也在RealInterceptorChain中
    return chain.proceed(originalRequest);
  }
public Response proceed(Request request) throws IOException {
    return proceed(request, streamAllocation, httpCodec, connection);
  }
  
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, connectTimeout, 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;
  }

这里要介绍几个重要的拦截器了,都继承自Interceptor,拦截器是一种强大的机制,可以做网络监视、重写和重试调用。类似于AOP的机制

  • RetryAndFollowUpInterceptor(重定向拦截器):负责处理错误,失败重试,重定向
  • BridgeInterceptor(桥接拦截器):负责设置编码方式,添加头部,Keep-Alive 连接以及应用层和网络层请求和响应类型之间的相互转换
  • CacheInterceptor(缓存拦截器):负责缓存的管理,期间也涉及到对网络状态的判断,更新缓存等
  • ConnectInterceptor(连接拦截器):负责与服务器建立链接,打开与目标服务器的连接,然后继续执行下一个拦截器。
  • CallServerInterceptor(调用服务器拦截器):负责发起网络请求和接受服务器返回响应,最后一个拦截器

再来看看加入的次序吧
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));
首先加入的是自定义的拦截器,这里跳过,再是RetryAndFollowUpInterceptor(重定向拦截器)之后类推
这里就不展开一 一介绍了,具体的作用已经在上方说明了。

到这里Okhttp的流程也就梳理完毕了
Okhttp具体使用到的设计模式有

  • 建造者模式:在OkhttpClient和Request创建时便会用到
  • 工程模式:在Call对象创建时,也就是那个interface Factory { Call newCall(Request request); }方法
  • 责任链模式:当然这是最主要的设计模式,充分的解耦

下面综合一下整个的流程
在这里插入图片描述

参考:
Okhttp3源码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值