OKHttp源码解析(一)

2021-12-07  本文已影响0人  HardMan

开局一张图,照着时序图,一步步理清

Okhttp主流程.png

1、构建OKHttpClient

OKHttpClient使用了Builder模式构造实例。可以对OKHttpClient进行一系列配置,譬如添加拦截器,设置超时时间等等

        OkHttpClient.Builder builder=new OkHttpClient.Builder();
        //设置拦截器、超时时间等等
        builder.addInterceptor();
        builder.connectTimeout();
        OkHttpClient client=builder.build();

2、构建Request

Request对象同样也是使用了Buidler模式,可以设置请求地址、请求头、请求方式等等

    public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

3、发起请求

当okhttpClient和request都已经准备就绪后,就可以开始发起请求了。
首先调用client的newCall方法,进到这个方法里面

Call call=client.newCall(request);
  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

这个过程其实就是构造了一个RealCall的对象,并将之返回。后面我们使用这个对象进行异步调用。

     call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

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

            }
        });
  @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的dispatcher()方法返回dispatcher对象,并调用它的enqueue方法。注意 在这个方法参数里 构造一个AsyncCall对象。那么这个对象是什么,我们进到里面去看

 final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    @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 {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

Asyncall继承了NamedRunnable,但NameRunnable实现了Runnable接口。从这里我们可以猜想到,Runnable对象是用来作什么的,大概率就是用来子线程调用的。所以我们先看下Dispatcher的enqueue方法。

  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

如果正在请求的个数没有超过maxRequests(64个)并且所有正在请求的Host个数没有超过maxRequestsPerHost(5个)时,并将Asyncall加入到请求队列中, 再执行executorService().execute(call)方法。否则加入等待队列。

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

到这里就很明显了,这是一个线程池,通过线程池进行请求。那么最终应该会执行Runnable的run方法。

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 {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

NameRunnable重写了run方法,并最终调用了AsyncCall的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 {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }

Response response = getResponseWithInterceptorChain() 看到这行代码,返回了请求结果Response,再通过Callback回调出去。

至于getResponseWithInterceptorChain里面到底做了 下篇再分析

上一篇下一篇

猜你喜欢

热点阅读