okHttp总结(一)

1,261 阅读3分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

一、使用

流程图

1.jpg

在使用OkHttp发起一次请求时,对于使用者最少存在OkHttpClient、Request与Call三个角色。其中OkHttpClient和Request的创建可以使用它为我们提供的Builder(建造者模式)。而Call则是把Request交给OkHttpClient之后返回的一个已准备好执行的请求

1. execute() 同步请求

一直等待http请求, 直到返回了响应. 在这之间会阻塞进程

override fun execute(): Response {
    //首先判断是否已执行过,如果已经执行过,则抛出异常信息,也就是说一次Call实例只能调用一次execute()方法
    check(executed.compareAndSet(false, true)) { "Already Executed" }
    timeout.enter()
    callStart()
    try {
        //如果未执行,则调用Dispatcher类的executed()方法将该Call加入到一个双端队列中
        client.dispatcher.executed(this)
        //调用getResponseWithInterceptorChain()方法返回Response对象
        return getResponseWithInterceptorChain()
    } finally {
        //从已经执行的双端队列中移除本次Call
        client.dispatcher.finished(this)
    }
}

@Synchronized internal fun executed(call: RealCall) {
    runningSyncCalls.add(call)
}

经过上面的分析,真正发出网络请求并返回结果的应该是getResponseWithInterceptorChain()方法

2. enqueuer 异步请求

在另外的工作线程中执行http请求, 请求时不会阻塞当前的线程

override fun enqueue(responseCallback: Callback) {
    //首先校验这个Call是否已经被执行,如果执行过,就报异常
    check(executed.compareAndSet(false, true)) { "Already Executed" }
    callStart()
    //调用Dispatcher分发器的enqueue()方法
    client.dispatcher.enqueue(AsyncCall(responseCallback))
}

AsyncCall是一个Runnable,在run()方法中调用了getResponseWithInterceptorChain()
inner class AsyncCall(private val responseCallback: Callback) : Runnable {
. . .
    override fun run() {
        threadName("OkHttp ${redactedUrl()}") {
        . . .
            try {
                val response = getResponseWithInterceptorChain()
                signalledCallback = true
                responseCallback.onResponse(this@RealCall, response)
            } catch (e: IOException) {
            . . .
            } finally {
                client.dispatcher.finished(this)
            }
        }
    }
}

2.jpg

一、核心原理分析

okHttp核心流程就是分发器(Dispatcher)和拦截器(Interceptors)

1. Dispatcher

Dispatcher用于执行网络请求任务,有4个核心成员对象: ExecutorService:线程池,用于执行异步任务 Deque:有三个队列(正在执行的同步任务、正在执行的异步任务、准备执行的异步任务)

2. Interceptors

okHttp最核心的工作就是在getResponseWithInterceptorChain()中 默认情况下有五大拦截器

  1. RetryAndFollowUpInterceptor:是第一个接触到请求,最后接触到响应,负责判断是否需要重新发起整个请求

      重试的前提是出现了RouteException或者IOException,一旦在后续的拦截器中执行过程中出现这两个异常,就会通过recover方法进行判断是否进行连接重试
    
      重定向发生在重试的判断之后,如果不满足重试条件,还需要进一步调用followUpRequest,根据Response的响应码(如果请求失败,Response都不存在就会抛出异常)
    
  2. BridgeInterceptor:补全请求,并对响应进行额外处理

      连接应用程序和服务器的桥梁,发出的请求将会经过它的处理才能发给服务器,比如设置内容长度,编码,gzip压缩,cookie等,获取响应后保存Cookie等操作
      对用户构建的Request进行添加或者删除相关头部信息,以转化成能够真正进行网络请求的Request,将符合网络请求规范的Request交给下一个拦截器处理,并获取Response
      如果响应体经过了GZIP压缩,那就需要解压,再构建成用户可用的Response并返回
    
  3. CacheInterceptor:请求前查询缓存,获得响应并判断是否需要缓存

      在发出请求前,判断是否命中缓存。如果命中则可以不请求,直接使用缓存的响应。 (只会存在Get请求的缓存)
      步骤:
     从缓存中获取对应请求的响应缓存
     创建CacheStrategy,创建时会判断是否能够使用缓存,在CacheStrategy中存在两个成员:netWorkRequest与cacheResponse
    
  4. networkInterceptors:与服务器完成TCP连接

     打开与目标服务器的连接,并执行下一个拦截器
    
  5. CallServerInterceptor:与服务器进行通信,封装请求数据与解析响应数据

    利用HttpCodec发出请求道服务器并解析生成Response