作为google主推的网络请求框架okhttp,很多时候我们都是拿过来直接用,对于内部怎么做到的却不知道。如果知道内部的流程,在对扩展和处理一些bug就容易多了,接下来就简单分析下请求流程
首选我们创建一个okhttpclient
// 使用默认的配置
val client = OkHttpClient.Builder().build()
接下来我们分别以get请求和post请求讲解
初始化我们的url请求信息
// 这个是配置操作 ,也可以直接对url写死的
val httpurl = HttpUrl.Builder()
.scheme("https")
.host("www.baidu.com")
// 添加路径
.addPathSegments("mobileapi2")
.addPathSegments("index.php")
// 添加参数
.addQueryParameter("act", "goods")
.addQueryParameter("op", "goods_list")
.build()
// 最后的url就像这样 https//"www.baidu.com/mobileapi2/index.php?act=goods&op=goods_list
如果是get请求可以接着使用addQueryParameter方法添加我们需要的参数,如果是post请求我们就需要在创建一个请求体Body
val builder = FormBody.Builder()
builder.addEncoded("page", "10")
builder.addEncoded("curpage", "1")
val formBody = builder.build()
然后通过创建request构建我们的一个请求
val request = Request.Builder()
.url(httpurl) // 配置的url信息
// .get() get请求
// .post(formBody) post请求 post独有的请求体
.build()
最后通过
// 异步
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
}
override fun onResponse(call: Call, response: Response) {
}
})
// 同步
client.newCall(request).execute()
就完成我们的请求了,那么内部怎么处理的呢?
我们首选看下newCall方法做了什么
// 创建了一个新的RealCall ,RealCall继承了Call 第一个参数是我们的client
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
我们接着看RealCall内部的enqueue方法
// 我们的client在构建的时候,默认初始化了dispatcher,dispatcher内部维护了线程池和请求队列
client.dispatcher.enqueue(AsyncCall(responseCallback))
创建一个AsyncCall。这个AsyncCall其实是一个Runnable,可以看作是我们请求的一个任务,dispatcher.enqueue方法就是将任务放入等待队列中
// dispatcher类
internal fun enqueue(call: AsyncCall) {
synchronized(this) {
// 将任务放入等待队列
readyAsyncCalls.add(call)
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.call.forWebSocket) {
val existingCall = findExistingCallWithHost(call.host)
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}
}
// 对任务开始处理
promoteAndExecute()
}
// dispatcher类
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf()
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
}
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
// 这个方法就是将我们的任务放入线程池中,交给线程池去处理
asyncCall.executeOn(executorService)
}
return isRunning
}
// AsyncCall类
fun executeOn(executorService: ExecutorService) {
client.dispatcher.assertThreadDoesntHoldLock()
var success = false
try {
// 将任务放入线程池中
executorService.execute(this)
success = true
} catch (e: RejectedExecutionException) {
val ioException = InterruptedIOException("executor rejected")
ioException.initCause(e)
noMoreExchanges(ioException)
responseCallback.onFailure(this@RealCall, ioException)
} finally {
if (!success) {
client.dispatcher.finished(this) // This call is no longer running!
}
}
}
然后就会执行AsyncCall的run方法
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
try {
// 使用默认提供的五大拦截器,对重定向,配置请求头,缓存,建立连接,对服务进行网络调用
val response = getResponseWithInterceptorChain()
signalledCallback = true
// Callback将我们得到的响应体回调
responseCallback.onResponse(this@RealCall, response)
} catch (e: IOException) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
} else {
// 错误信息回调
responseCallback.onFailure(this@RealCall, e)
}
} catch (t: Throwable) {
cancel()
if (!signalledCallback) {
val canceledException = IOException("canceled due to $t")
canceledException.addSuppressed(t)
responseCallback.onFailure(this@RealCall, canceledException)
}
throw t
} finally {
client.dispatcher.finished(this)
}
}
}
}
至此我们就完成了post请求
get请求流程比post就简单了
// newCall和post一样 ,主要看execute
val response= client.newCall(request).execute()
//
override fun execute(): Response {
check(executed.compareAndSet(false, true)) { "Already Executed" }
timeout.enter()
callStart()
try {
// this 就是call 通过我们的dispatcher将任务放入到 runningSyncCalls队列中
client.dispatcher.executed(this)
// 通过默认的五大拦截器 就得到我们服务的响应数据
return getResponseWithInterceptorChain()
} finally {
client.dispatcher.finished(this)
}
}