OkHttp源码分析 - 同步请求过程

66 阅读2分钟

相对于异步请求,同步请求更加简洁。通过OkHttpClient创建RealCall对象后,调用RealCallexecute方法即可开启一个同步请求。同步请求的开启方式如下:

// 创建Request对象
val request = Request.Builder()
    .url("https://example.com")
    .build()

// 创建OkHttpClient对象
val okHttpClient = OkHttpClient()

// 通过OkHttpClient对象和Request对象,创建RealCall对象
val call = okHttpClient.newCall(request)

// 开启同步请求,并得到响应结果
val response: Response = call.execute()

RealCallexecute方法内部实现比较简单。如果理解了异步请求过程,同步请求过程也很容易理解。源码如下:

override fun execute(): Response {
    // 检查是否重复调用executed方法
    check(executed.compareAndSet(false, true)) { "Already Executed" }

    timeout.enter()
    callStart()
    try {
        // 调用dispatcher的executed方法,将RealCall添加到正在运行的同步请求队列runningSyncCalls中
        client.dispatcher.executed(this)
        // 通过拦截器链得到网络响应
        return getResponseWithInterceptorChain()
    } finally {
        // 请求完成后调用该方法,发出完成信号
        client.dispatcher.finished(this)
    }
}

Dispatcher的executed方法

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

RealCallexecute方法中,先通过dispatcherRealCall添加到正在运行的同步请求队列runningSyncCalls中,然后通过拦截器链得到网络响应,getResponseWithInterceptorChain方法在分析异步请求时已经介绍过了。最后调用dispatcher.finished(this),完成本次请求,并开始处理下一个请求。

完整的同步请求流程总结

  1. 创建请求:构建Request对象,并通过OkHttpClient创建一个新的RealCall对象。
  2. 启动请求:调用RealCallexecute方法启动同步请求。
  3. 添加到调度器RealCall通过dispatcherexecuted方法将自身添加到runningSyncCalls队列。
  4. 拦截器链处理:通过getResponseWithInterceptorChain方法,经过一系列的拦截器处理请求并得到响应。
  5. 完成请求:调用dispatcher.finished(this),从runningSyncCalls队列中移除,发出完成信号。

通过以上步骤,OkHttp能够有效地处理同步请求,确保请求的顺序和并发控制。