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的整个调用的流程图
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值