1、OkHttp恳求整体流程是怎样的

OkHttp源码流程简述

  • 构建OkhttpClient目标
  • 构建Request目标
  • Request传入到newCall办法生成Realcall目标,用它来建议新恳求
  • 分发器维护恳求行列和线程池,完结恳求调配
    • 同步-》realcall中的execute办法,client.dispatcher().executed(this);履行runningSyncCalls.add(call); 再履行getResponseWithInterceptorChain
    • 异步-》realcall中的enqueue办法,client.dispatcher().enqueue(new AsyncCall(responseCallback));分发器中加到异步恳求行列。再线程池恳求,终究调用到getResponseWithInterceptorChain
  • 履行getResponseWithInterceptorChain跑到阻拦器
  • 履行chain.proceed(originalRequest)回来成果Response

2、分发器是怎么作业的?

2.1 同步

  • Realcall.execute() 会跑到分发器Dispatcher.java 履行execute()

  • 加到runningSyncCalls也就是同步线程行列中

  • 调用getResponseWithInterceptorChain()运行阻拦器用的责任链形式,终究回来Response

  • 用完移除RealCall 调用client.dispatcher().finished(this);

-------------Realcall.java
@Override public Response execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  transmitter.timeoutEnter();
  transmitter.callStart();
  try {
  //1、 分发器履行execute 传入
    client.dispatcher().executed(this);
  // 2、履行getResponseWithInterceptorChain()
    return getResponseWithInterceptorChain();
  } finally {
  //3、用完移除RealCall
    client.dispatcher().finished(this);
  }
}
-------------Dispatcher.java
synchronized void executed(RealCall call) {
  runningSyncCalls.add(call);
}

2.2 异步

2.2.1 异步履行流程

  • Realcall.enqueue(new AsyncCall())
  • 恳求数不超过64,且同一host恳求不能超过5个。
    • 加入到runningAsyncCalls
    • 加入到线程池中中履行,executorService().execute(call);
    • 每个使命完结后,都会调用分发器的finished办法,这儿面会取出等候行列readyAsyncCalls中的使命继续履行
  • 否则加入到等候行列readyAsyncCalls中
-------------Dispatcher.java
synchronized void enqueue(AsyncCall call) {
    //恳求数最大不超过64,同一Host恳求不能超过5个
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost)     {
        runningAsyncCalls.add(call);
        executorService().execute(call);
    } else {
        readyAsyncCalls.add(call);
    }
}

2.2.2 异步AysncCall类剖析

  • AysncCall承继了抽象类NamedRunnable,线程池终究会跑AysncCall的run办法,履行到了AysncCall的execute办法,跑到getResponseWithInterceptorChain()
final class AsyncCall extends NamedRunnable {
  private final Callback responseCallback;
  private volatile AtomicInteger callsPerHost = new AtomicInteger(0);
  AsyncCall(Callback responseCallback) {
    super("OkHttp %s", redactedUrl());
    this.responseCallback = responseCallback;
  }
 ...
  @Override protected void execute() {
    boolean signalledCallback = false;
    transmitter.timeoutEnter();
    try {
      Response response = getResponseWithInterceptorChain();
      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 {
        responseCallback.onFailure(RealCall.this, e);
      }
    } catch (Throwable t) {
      cancel();
      if (!signalledCallback) {
        IOException canceledException = new IOException("canceled due to " + t);
        canceledException.addSuppressed(t);
        responseCallback.onFailure(RealCall.this, canceledException);
      }
      throw t;
    } finally {
      client.dispatcher().finished(this);
    }
  }
}

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

3、阻拦器怎么作业?

  • 责任链设计是 将恳求者履行者进行解耦,恳求发了,不用关怀细节。这个链上的每一个节点都有机会处理恳求,处理完了交给下一个,呈一个U形结构。如下图所示。CallServerInterceptorintercept办法,此办法会将网络呼应的成果封装成一个Response目标并return

    OkHttp源码流程简述

    • 应用阻拦器(用户可自定义)
      • 拿到最原始恳求,能够添加自定义header、通用参数等
    • 重试重定向阻拦器
      • 处理过错重试和重定向
    • 桥接阻拦器
      • 应用层和网络层的桥接阻拦器,主要作业是条件cookie、固定和header,保存成果的cookie,如呼应用过gzip压缩过,就还需要解压
    • 缓存阻拦器
      • 假如命中缓存则不会建议网络恳求
    • 衔接阻拦器
      • 内部维护一个衔接池,负责衔接服用、创立衔接(3次握手)、释放衔接以及创立衔接上的socket流
    • 网络阻拦器(用户可自定义)
      • 通常用于检测网络层的数据衔接
    • 恳求服务阻拦器
      • 前置准备作业完结后,真正建议网络恳求
Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(client.interceptors());
  interceptors.add(new RetryAndFollowUpInterceptor(client));
  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, transmitter, null, 0,
      originalRequest, this, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());
  boolean calledNoMoreExchanges = false;
  try {
    Response response = chain.proceed(originalRequest);
    if (transmitter.isCanceled()) {
      closeQuietly(response);
      throw new IOException("Canceled");
    }
    return response;
  } catch (IOException e) {
    calledNoMoreExchanges = true;
    throw transmitter.noMoreExchanges(e);
  } finally {
    if (!calledNoMoreExchanges) {
      transmitter.noMoreExchanges(null);
    }
  }
}

OkHttp源码流程简述