美文网首页
Okhttp源码分析

Okhttp源码分析

作者: JianLee | 来源:发表于2020-01-11 10:05 被阅读0次
版本:4.3.1

框架流程

image.png
  • 创建OkHttpClient对象
  • 创建Request对象
  • 通过OkHttpClient将Request封装成Call对象
  • 通过Call执行请求同步/异步(实际是由Dispatcher进行调度)
  • 通过Interceptors处理请求与响应

基本使用

  //1.创建OkHttpClient对象
        //OkHttpClient client = new OkHttpClient();
        //Builder
        OkHttpClient client = new OkHttpClient().newBuilder().readTimeout(5, TimeUnit.SECONDS).build();
        //2.创建Request对象
        Request request = new Request.Builder()
                .url(url)
    .get()//默认就是GET请求,可以不写
                .build();
         //3.通过OkHttpClient将Request封装成Call对象
        Call call = client.newCall(request);
         //4.执行同步请求
  Response response = call.execute();
         //4.执行异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("okHttp", "onFailure: ");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d("okHttp", "onResponse: " + response.body().string());
            }
        });

源码分析

  • 不管是同步请求还是异步请求,都必须先创建OkHttpClient和Request对象
Dispatcher任务调度器在OkHttpClient.Builder()进行构建
 class Builder constructor() {
    internal var dispatcher: Dispatcher = Dispatcher()// 调度器
    internal var connectionPool: ConnectionPool = ConnectionPool()  // 连接池
    internal val interceptors: MutableList<Interceptor> = mutableListOf() // 拦截器
    internal val networkInterceptors: MutableList<Interceptor> = mutableListOf() // 网络拦截器
    internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()
    internal var retryOnConnectionFailure = true  // 重试连接失败
    internal var authenticator: Authenticator = Authenticator.NONE  // 本地身份验证
    internal var followRedirects = true // 本地重定向
    internal var followSslRedirects = true // 安全套接层重定向
    internal var cookieJar: CookieJar = CookieJar.NO_COOKIES // cookie
    internal var cache: Cache? = null  // 缓存
    internal var dns: Dns = Dns.SYSTEM  // 域名
    internal var proxy: Proxy? = null // 代理
    internal var proxySelector: ProxySelector? = null // 代理选择器
    internal var proxyAuthenticator: Authenticator = Authenticator.NONE // 代理身份验证
    internal var socketFactory: SocketFactory = SocketFactory.getDefault()  // socket 工厂
    internal var sslSocketFactoryOrNull: SSLSocketFactory? = null // 安全套接层 socket 工厂,用于 https
    internal var x509TrustManagerOrNull: X509TrustManager? = null
    internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS  // 传输层版本和连接协议
    internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS // 协议
    internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier // 主机名字验证
    internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT // 证书链
    internal var certificateChainCleaner: CertificateChainCleaner? = null // 验证确认响应证书 适用 HTTPS 请求连接的主机名
Request.Builder()
    constructor() {
      this.method = "GET"
      this.headers = Headers.Builder()
    }
不管同步请求还是异步请求,都是调用Call(类RealCall)的方法执行
  //同步请求
  override fun execute(): Response {
    synchronized(this) {
      // 每个 call 只能执行一次
      check(!executed) { "Already Executed" }
      executed = true
    }
    transmitter.timeoutEnter()
    transmitter.callStart()
    try {
      // 请求开始, 将自己加入到runningSyncCalls队列中
      //真正请求的是dispatcher.executed方法
      client.dispatcher.executed(this)
      // 通过一系列拦截器请求处理和响应处理得到最终的返回结果
      return getResponseWithInterceptorChain()
    } finally {
      //执行完成之后从队列中移除请求
      client.dispatcher.finished(this)
    }
  }

  @Throws(IOException::class)
  fun getResponseWithInterceptorChain(): Response {
    // Build a full stack of interceptors.
    // 配置 OkhttpClient 时设置的拦截器
    val interceptors = mutableListOf<Interceptor>()
    interceptors += client.interceptors
    // 负责失败重试以及重定向
    interceptors += RetryAndFollowUpInterceptor(client)
    // 负责封装 request 和 response
    interceptors += BridgeInterceptor(client.cookieJar)
    // 缓存相关的拦截器,负责读取缓存直接返回、更新缓存
    interceptors += CacheInterceptor(client.cache)
    // 负责和服务器建立连接
    interceptors += ConnectInterceptor
    if (!forWebSocket) {
      interceptors += client.networkInterceptors
    }
    // 负责向服务器发送请求数据、从服务器读取响应数据
    interceptors += CallServerInterceptor(forWebSocket)

同步请求调用realCall.executed方法,在该方法中调用dispatcher.executed将realCall添加到同步运行对列中runningSyncCalls然后调用getResponseWithInterceptorChain获取响应报文。
//异步请求
  override fun enqueue(responseCallback: Callback) {
    synchronized(this) {
      check(!executed) { "Already Executed" }
      executed = true
    }
    transmitter.callStart()
 //封装成了AsyncCall,它就是一个Runable
    client.dispatcher.enqueue(AsyncCall(responseCallback))
  }
  private fun promoteAndExecute(): Boolean {
    this.assertThreadDoesntHoldLock()

    val executableCalls = mutableListOf<AsyncCall>()
    val isRunning: Boolean
    synchronized(this) {
      val i = readyAsyncCalls.iterator()
      while (i.hasNext()) {
        val asyncCall = i.next()
        // 正在运行的异步请求超过64
        if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
        // 同一个host下的异步请求超过5个
        if (asyncCall.callsPerHost().get() >= this.maxRequestsPerHost) continue // Host max capacity.

        i.remove()
        asyncCall.callsPerHost().incrementAndGet()
        executableCalls.add(asyncCall)
        runningAsyncCalls.add(asyncCall)
      }
      isRunning = runningCallsCount() > 0
    }

异步请求的时候,通过dispatcher.enqueue方法将call(封装成了Runable(AsyncCall,它是RealCall的的内部类))添加到就绪对列中,然后循环就绪对列,如果现在执行的任务数没有超过最大的请求数(64)就添加到执行对列中,然后执行asyncCall.executeOn(executorService());。
Dispatcher任务调度

Dispatcher的各个参数的说明如下:

  //支持的最大并发请求数量
  @get:Synchronized var maxRequests = 64
    set(maxRequests) {
      require(maxRequests >= 1) { "max < 1: $maxRequests" }
      synchronized(this) {
        field = maxRequests
      }
      promoteAndExecute()
    }

  //每个主机的最大请求数量
  @get:Synchronized var maxRequestsPerHost = 5
    set(maxRequestsPerHost) {
      require(maxRequestsPerHost >= 1) { "max < 1: $maxRequestsPerHost" }
      synchronized(this) {
        field = maxRequestsPerHost
      }
      promoteAndExecute()
    }

  //请求线程池
  private var executorServiceOrNull: ExecutorService? = null
  //将要运行的异步请求队列
  private val readyAsyncCalls = ArrayDeque<AsyncCall>()

  //正在运行的异步请求队列
  private val runningAsyncCalls = ArrayDeque<AsyncCall>()

  //正在运行的同步请求队列
  private val runningSyncCalls = ArrayDeque<RealCall>()
  • maxRequests :OkHttp支持的最大并发请求数量

  • maxRequestsPerHost :每个主机的最大请求数量

  • readyAsyncCalls :将要运行的异步请求队列

  • runningAsyncCalls :正在运行的异步请求队列

  • runningSyncCalls :正在运行的同步请求队列

Dispatcher的executorService方法,如下:
  @get:Synchronized
  @get:JvmName("executorService") val executorService: ExecutorService
    get() {
      if (executorServiceOrNull == null) {
        executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
            SynchronousQueue(), threadFactory("OkHttp Dispatcher", false))
      }
      return executorServiceOrNull!!
    }

Dispatcher初始化了一个线程池,核心线程的数量为0 ,最大的线程数量为Integer.MAX_VALUE,空闲线程存在的最大时间为60秒。

再来看一遍流程图进行总结

image.png
  • 同步方法总结
  1. 创建OkHttpClient和Request对象
  2. 将Request封装成Call对象
  3. 调用Call的execute发送同步请求
  4. 发送请求之后就会进入阻塞状态,直到收到响应
  • 异步方法总结
  1. 创建OkHttpClient和Request对象
  2. 将Request封装成Call对象
  3. 调用Call的enqueue进行异步请求
  4. 发送请求之后就会进入阻塞状态,直到收到响应
  5. 判断当前call对象,创建一个AsyncCall队列,执行dispatcher的enqueue方法。
okhttp中的拦截器
  @Throws(IOException::class)
  fun getResponseWithInterceptorChain(): Response {
    // Build a full stack of interceptors.
    // 配置 OkhttpClient 时设置的拦截器
    val interceptors = mutableListOf<Interceptor>()
    interceptors += client.interceptors
    // 负责失败重试以及重定向
    interceptors += RetryAndFollowUpInterceptor(client)
    // 负责封装 request 和 response
    interceptors += BridgeInterceptor(client.cookieJar)
    // 缓存相关的拦截器,负责读取缓存直接返回、更新缓存
    interceptors += CacheInterceptor(client.cache)
    // 负责和服务器建立连接
    interceptors += ConnectInterceptor
    if (!forWebSocket) {
      interceptors += client.networkInterceptors
    }
    // 负责向服务器发送请求数据、从服务器读取响应数据
    interceptors += CallServerInterceptor(forWebSocket)
  1. 在配置 OkHttpClient 时设置的 interceptors ()

  2. 负责失败重试以及重定向的RetryAndFollowUpInterceptor

  3. 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转为用户友好的响应的 BridgeInterceptor

  4. 负责读取缓存直接返回、更新缓存的 CacheInterceptor

  5. 负责和服务器建立连接的 ConnectInterceptor

  6. 配置 OkHttpClient 时设置的 networkInterceptors

  7. 负责向服务器发送请求数据、从服务器读取响应数据的 CallServerInterceptor

  8. 在 return chain.proceed(originalRequest),中开启链式调用

相关文章

网友评论

      本文标题:Okhttp源码分析

      本文链接:https://www.haomeiwen.com/subject/gvyvactx.html