美文网首页
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