OkHttp源码分析--执行流程

1.创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
OkHttp的创建采用了构建者模式,OkHttpClient.Builder()无参构造方法为 OkHttpClient的属性提供了默认值。
public Builder() {
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }
2.创建Request
Request request = new Request.Builder().url("https://www.baidu.com").get().build();
Request的创建也采用了构建者模式,Request的属性包括url、请求方法、请求头、请求体、标签,在Request.Builder()中为Request设置的默认请求方法是“GET”。
final HttpUrl url;
  final String method;
  final Headers headers;
  final @Nullable RequestBody body;
  final Object tag;
  
public Builder() {
      this.method = "GET";
      this.headers = new Headers.Builder();
}
3.创建Call
Call call = okHttpClient.newCall(request);
okHttpClient.newCall方法如下:
@Override 
public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
Call是一个接口,该接口提供了同步请求、异步请求、取消请求等方法,RealCall是其实现类,在RealCall的newRealCall方法中,通过传入OkHttpClient和Request对象创建了一个RealCall对象,
  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;
  }
4.同步请求
Response response = call.execute();
RealCall的execute方法如下:
  @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);
    }
  }
首先判断请求有没有执行过,如果请求已经执行过,再次执行会抛出“Already Executed”异常。
client.dispatcher().executed(this)会将RealCall对象放入双端队列中。
 private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }
getResponseWithInterceptorChain()方法如下:
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);
  }
getResponseWithInterceptorChain使用了责任链模式,将网络请求用到的多个拦截器形成一个链条,Request请求经过多个拦截器的处理返回Response对象。
无论请求是否成功,在finally中执行client.dispatcher().finished(this),将RealCall对象从双端队列中移除。
5.异步请求
call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                System.out.println("请求失败: " + e.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                System.out.println("请求成功: " + string);
            }
        });
RealCall的enqueue方法如下:
  @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));
  }
首先判断请求有没有执行过,然后把用户创建的回调封装到AsyncCall对象中,执行DisPatcher的enqueue方法,如下:
  //异步请求准备队列
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
  //异步请求执行队列
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }
maxRequests的值是64,代表同时请求的最大数量,maxRequestsPerHost的值是5,代表每个服务器的最大请求数量,当满足条件时,会将AsyncCall放到执行队列中,并使用线程池执行该请求,当不满足条件时,会将AsyncCall放到准备队列中。
executorService()创建了一个缓存线程池,当线程空闲时间小于1分钟时,如果提交新的任务,会进行线程的复用,如果线程空闲时间超过1分钟,线程会终止,如果此时提交新任务,线程池会创建新的线程来处理。
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;
  }
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) {
          // 用户的回调中出现异常
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
        //OkHttp的请求出现异常
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
在AsyncCall的execute中依然使用了责任链模式进行请求。使用了signalledCallback标识用来区分异常来自用户的回调或OkHttp请求过程。
在finished方法中,除了移除准备队列的AsyncCall,还要把准备队列的AsyncCall移动到执行队列中。
  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }
private void promoteCalls() {
    if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();
	//把准备队列的AsyncCall移到执行队列中
      if (runningCallsForHost(call) < maxRequestsPerHost) {
        i.remove();
        runningAsyncCalls.add(call);
        executorService().execute(call);
      }

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值