相对于异步请求,同步请求更加简洁。通过OkHttpClient创建RealCall对象后,调用RealCall的execute方法即可开启一个同步请求。同步请求的开启方式如下:
// 创建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()
RealCall的execute方法内部实现比较简单。如果理解了异步请求过程,同步请求过程也很容易理解。源码如下:
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)
}
在RealCall的execute方法中,先通过dispatcher将RealCall添加到正在运行的同步请求队列runningSyncCalls中,然后通过拦截器链得到网络响应,getResponseWithInterceptorChain方法在分析异步请求时已经介绍过了。最后调用dispatcher.finished(this),完成本次请求,并开始处理下一个请求。
完整的同步请求流程总结
- 创建请求:构建
Request对象,并通过OkHttpClient创建一个新的RealCall对象。 - 启动请求:调用
RealCall的execute方法启动同步请求。 - 添加到调度器:
RealCall通过dispatcher的executed方法将自身添加到runningSyncCalls队列。 - 拦截器链处理:通过
getResponseWithInterceptorChain方法,经过一系列的拦截器处理请求并得到响应。 - 完成请求:调用
dispatcher.finished(this),从runningSyncCalls队列中移除,发出完成信号。
通过以上步骤,OkHttp能够有效地处理同步请求,确保请求的顺序和并发控制。