Okhttp 的源码解析--(1)

该文章是对Okhttp的源码解析

一.OkHttpClient,Request的构建
1.1. OkHttpClient有两种构造方式

1.默认方式

public OkHttpClient() {
    this(new Builder());
  }
OkHttpClient(Builder builder){
  builder.xxx
}

2.builder模式
OkHttpClient
——Builder

   public OkHttpClient build() {
              return new OkHttpClient(this);
    }

通过Builder配置参数,最后使用builder方法返回一个OkHttpClient实例(Ps:这个builder 的设置在我们开发中很好用)

以上使用两种设计模式: 1.Builder模式 2.外观模式

1.2. Request有两种构造方式

唯一的构造函数:

  Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tag = builder.tag != null ? builder.tag : this;
  }

说明必须要先构建一个Request.Builder,然后才能构建

public Builder newBuilder() {
    return new Builder(this);
  }
//builder===================
public Builder() {
      this.method = "GET";
      this.headers = new Headers.Builder();
    }

Builder(Request request) {
      this.url = request.url;
      this.method = request.method;
      this.body = request.body;
      this.tag = request.tag;
      this.headers = request.headers.newBuilder();
    }
public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

由此可见,又是builder模式,同时默认了GET请求,同时可以传人Request做完参数,构建相同配置的Request

二.异步请求

不管同步/异步请求,其实质的执行流程除了异步外,基本都是一致的

构建完成Request后,再构建一个Call,使用如下:

    Call call = http.newCall(request)

源码:

  /**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }

注意这个是Override 复写的方法,复写的接口是Call.Factory

interface Factory {
    Call newCall(Request request);
  }

小结:仅仅定义一个newCall用于创建Call的方法,这里用到工厂模式的思想,将构建的细节交给具体实现,顶层只需要拿到Call对象即可

我们继续看RealCall的方法newRealCall方法做了什么

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;
  }

其中:final class RealCall implements Call;就是说Call的本质是:RealCall,同时创建一个evenListener:很明显是一个事件的监听器.

而我们看看RealCall的构造函数,创建rertyAndFollowUpInterceptor过滤器,这个就是OkHttp的巨大亮点,根据这个过滤器,我们可以给okhttp增添很多好的定制化工作

 private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);//这里就是亮点
  }

三.最后就是正式请求(enqueue-异步的,excute-同步的)

3.1 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));
  }
  1. 使用synchronized 加入对象锁,excute是判断是否被执行
  2. captureCallStackTrace():加入了一个用于追踪堆栈信息的callStackTrace,
  3. eventListener.callStart(this); eventListener起到作用了,调用了callStart方法
  4. client.dispatcher().enqueue(new AsyncCall(responseCallback));
 public Dispatcher dispatcher() {
    return dispatcher;
  }

返回了一个DisPatcher对象

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

然后看看Dispatcher的成员变量

public final class Dispatcher {
  private int maxRequests = 64;
  private int maxRequestsPerHost = 5;
  private @Nullable Runnable idleCallback;

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

  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
...

可以看出,这里的三个队列Deque用于保存Call对象,分别三种状态,异步等待,同步running,异步running;

所以:

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

的意思是正在执行的异步队列个数校园MaxRequest 并且请求同一个主机个数校园MaxRequestsPerHost()时候,则将这个请求加入异步执行队列runningAsyncCall,并用线程池执行这个call,否则加入异步等待队列.

private int runningCallsForHost(AsyncCall call) {
    int result = 0;
    for (AsyncCall c : runningAsyncCalls) {
      if (c.host().equals(call.host())) result++;
    }
    return result;
  }

变量runningAsyncCalls,记录同一个Host的个数(小于5️⃣才能加入异步执行队列),否则就加入异步等待队列

现在重点是AsynCall()
回顾一下public AsynCall(RealCall);所有他是用于realCall的引用,而且他是RealCall的内部类

源码

 final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

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

他基础与NamedRunnabl ,NamedRunnable基础与Runnable;可以看出,这里讲执行的线程额名字设为我们在构造方法中的名字,接着执行execute,其实就这里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);
    }
  }

  protected abstract void execute();
}

然后回到AsyCall中的excute()方法

@Override protected void execute() {
      boolean signalledCallback = false;
      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) {
        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);
      }
    }

小结:RealCall,做完成参数生成AsynCall;AsynCall 根据不同情况放在在Dispather 的不同堆栈中(分别是,运行,等待)中;
AsynCall继承runnable,runnable 最终调用excute()方法;而excute方法就是执行网络请求的(无论是异步/同步);而执行网络
请求最重要的方法是:getResponseWithInterceptorChain()方法,该方法返回Response ;

那么就是说所谓的网络请求的是执行:getResponseWithInterceptorChain()方法直接抛每个,可以说 getResponseWithInterceptorChain就是说 OkHttp的精髓了.
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.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }

以上源码表明Okhttp,就是使用Interceptor的方法将request 层层处理,以下是默认拦截器的作用

拦截器名称 用处
retryAndFollowUpInterceptor 失败和重定向拦截器
BridgeInterceptor 封装request和response过滤器
CacheInterceptor 缓存相关的过滤器
ConnectInterceptor 负责和服务器建立连接,连接池等
networkInterceptors 配置 OkHttpClient 时设置的 networkInterceptors
CallServerInterceptor 负责向服务器发送请求数据、从服务器读取响应数据(实际网络请求)
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;
    。。。

    // 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);

    。。。

    return response;
  }

index构造函数传进来的,初始为0;然后增加,如果index 穿过过滤器个数抛出异常,后面new一个RealInterceptorChain,接着
获取index的interceptor,并调用intercept方法,传人新new的next对象;
其实就是这个RealInterceptorChain就是一个包装了请求的的包装类,我是使用递归的方法,对拦截器的集合的遍历

Q:那么他们是怎么实现每个拦截器都能执行一个遍历的呢?
A:原因在:每个拦截器复写intercept方法,里面执行proceessed,同时该Chain 的构造函数index+1,一直到拦截器集合超出就停止

@Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    。。。暂时没必要看。。。

    return realChain.proceed(request, streamAllocation, httpCodec, connection);
  }

这里讲RealInterceptionChain给interceptor层层传递,就是经典的责任链设计模式

四.同步请求

@Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }

也是调用getResponseWithInterceptorChain()

以下是OkHttp的整个调用的流程图
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qianyedoufulao/article/details/80482545