【OkHttp】OkHttp 源码分析 ( 同步 / 异步 Request 请求执行原理分析 )(一)

文章目录

OkHttp 系列文章目录

一、分析 OkHttp 执行原理

1、创建 OkHttpClient

2、创建 Request

3、获取 RealCall

4、通过 RealCall 发送 同步 / 异步 Request 请求

( 1 ) 、同步 Request 请求

( 2 ) 、异步 Request 请求

二、OkHttp 异步 Request 请求源码分析

1、Dispatcher 调度器 enqueue 方法分析

2、Dispatcher 调度器 promoteAndExecute 方法分析

3、AsyncCall 的 executeOn 方法分析

三、OkHttp 请求时序图参考

四、博客资源





一、分析 OkHttp 执行原理


以 OkHttp 同步 / 异步 Get 请求为例 , 分析底层的运行细节 ;


   /**

/**
     * OkHttp 异步 Get 请求
     */
    private void httpAsynchronousGet() {
        // 初始化 OkHttp 
  OkHttpClient mOkHttpClient = new OkHttpClient();
        // Request 中封装了请求相关信息
        Request request = new Request.Builder()
                .url("https://www.baidu.com")   // 设置请求地址
                .get()                          // 使用 Get 方法
                .build();
        // 异步 Get 请求
        mOkHttpClient.newCall(request).enqueue(new Callback(){
            @Override
            public void onFailure(Call call, IOException e) {
                // 请求失败的情况
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 请求成功 , 获取
                String result = response.body().string();
                Log.i(TAG, "result : " + result);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 主线程中执行相关代码
                    }
                });
            }
        });
    }

   

1、创建 OkHttpClient


创建 OkHttpClient : 调用者调用 OkHttpClient 构造函数 , 创建 OkHttpClient , 然后返回给调用者 ;


OkHttpClient mOkHttpClient = new OkHttpClient();


OkHttpClient 构造函数中 , 实际上创建了自身的创建者 ;
  public OkHttpClient() {
    this(new Builder());
  }


上述创建者构造函数调用的是无参构造函数 , 也就是默认设置了一系列参数 , 如下 :


public static final class Builder {
    public Builder() {
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      if (proxySelector == null) {
        proxySelector = new NullProxySelector();
      }
      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;
      callTimeout = 0;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }
  }



2、创建 Request


创建 Request 时 , 使用 Request 的创建者 Request.Builder 创建该 Request 对象 ;


先调用 Request.Builder 的构造函数 , 创建 Request.Builder 对象 , 然后调用 Request.Builder 的 build 方法 , 创建 Request 对象 ;


// Request 中封装了请求相关信息
Request request = new Request.Builder()
        .url("https://www.baidu.com")   // 设置请求地址
        .get()                          // 使用 Get 方法
        .build();



3、获取 RealCall


调用 OkHttpClient 对象的 newCall 方法 , 发起新的请求调用 , 返回 1 11 个 RealCall 类型对象 ;


mOkHttpClient.newCall(request)


在 OkHttpClient 的 newCall 方法中 , 创建了 RealCall , 并返回给了调用者 ;


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


RealCall 实现了 Call 接口 ;


final class RealCall implements Call {
  final OkHttpClient client;
}


Call 接口提供的功能 : execute 是同步请求 , enqueue 是异步请求 ;


public interface Call extends Cloneable {
  Request request();
  Response execute() throws IOException;
  void enqueue(Callback responseCallback);
  void cancel();
  boolean isExecuted();
  boolean isCanceled();
  Timeout timeout();
  Call clone();
  interface Factory {
    Call newCall(Request request);
  }
}



4、通过 RealCall 发送 同步 / 异步 Request 请求


RealCall 实现了上述 Call 接口的各项功能 , 主要关注其实现 Call 接口的 execute 同步请求方法 , enqueue 异步请求方法 ;


final class RealCall implements Call {
  @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.timeoutEnter();
    transmitter.callStart();
    try {
      client.dispatcher().executed(this);
      // 返回一个责任链 
      return getResponseWithInterceptorChain();
    } finally {
      client.dispatcher().finished(this);
    }
  }
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.callStart();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
}


( 1 ) 、同步 Request 请求


同步请求方法 , 返回一个责任链 , 在该方法中可以清楚的看到 OkHttp 的 Get 请求具体做了哪些步骤 ;

在该方法中通过添加不同功能的拦截器 , 实现相关业务路基 ;


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




( 2 ) 、异步 Request 请求


在 RealCall 的 enqueue 异步请求方法中 , 最终调用的还是 OkHttpClient 的 dispatcher 进行调度 ;


在上一篇博客 【OkHttp】OkHttp 源码分析 ( OkHttpClient.Builder 构造器源码分析 ) 已经提到过 OkHttpClient 的 Dispatcher dispatcher 成员 , 是 Get / Post 方法的请求线程调度器 ;


final class RealCall implements Call {
  final OkHttpClient client;
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.callStart();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
}




上一篇:使用ulimit设置文件最大打开数


下一篇:【OkHttp】OkHttp 源码分析 ( 同步 / 异步 Request 请求执行原理分析 )(一)