美文网首页
OKHttp源码解析(一)

OKHttp源码解析(一)

作者: HardMan | 来源:发表于2021-12-07 20:45 被阅读0次

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

    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里面到底做了 下篇再分析

    相关文章

      网友评论

          本文标题:OKHttp源码解析(一)

          本文链接:https://www.haomeiwen.com/subject/zovaxrtx.html