okhttp使用
okhttp则分为Request请求与response响应。
request请求体:每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。
response 响应码:响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
封装的okhttp库与okhttp使用:
blog.csdn.net/xjz123456qq…
基本请求(GET POST)
GET
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException error) {
//响应失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//响应成功
}
});
POST
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
client.newCall(
new Request.Builder()
.url(url)
// .headers()//添加头
.post(body)
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
LogUtil.i("http response " + response);
if (response.isSuccessful()) {
}
}else {
}
}
});
okhttp请求流程与源码解析
由上面请求可以看出同步与异步,都是通过newCall()去实现的,那么newCall()到底了实现了什么呢?
//返回了一个Call对象
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
同步请求 call.execute()
override fun execute(): Response {
//先判断一下当前是否请求过
check(executed.compareAndSet(false, true)) { "Already Executed" }
timeout.enter()
callStart()
try {
//分发器进行分发
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()// 走拦截器
} finally {
client.dispatcher.finished(this)//完成后的回调
}
}
/** Used by [Call.execute] to signal it is in-flight. */
@Synchronized internal fun executed(call: RealCall) {
runningSyncCalls.add(call)//直接去正在运行的同步队列中取值
}
源码可以看到,同步拦截器,直接去正在执行的同步队列中取值。
异步请求
override fun enqueue(responseCallback: Callback) {
//先判断当前这个call是否已经执行,执行了抛异常
check(executed.compareAndSet(false, true)) { "Already Executed" }
callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))//走异步的分发
}
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()
}
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
}
//对临时队列里的任务进行处理,迭代处理
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
asyncCall.executeOn(executorService)//放到线程池中进行处理
}
return isRunning
}
//异步处理任务的源码
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
try {
// 执行请求,走拦截器
val response = getResponseWithInterceptorChain()
signalledCallback = true
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)//完成之后的回调
}
}
}
/** Used by [Call.execute] to signal completion. */
internal fun finished(call: RealCall) {
finished(runningSyncCalls, call)
}
private fun <T> finished(calls: Deque<T>, call: T) {
val idleCallback: Runnable?
synchronized(this) {
if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")
idleCallback = this.idleCallback
}
val isRunning = promoteAndExecute()//完成这次任务请求后,去进行下一次请求
if (!isRunning && idleCallback != null) {
idleCallback.run()
}
}
上面可以看出,RealCall中有三个队列
1、正在执行的同步队列 2、正在执行的异步队列 3、准备执行的异步队列,任务进行排队准备的队列
异步请求流程:
1、enqueue()后,先判断当前任务是否被执行,没有执行走分发器的分发 2、先把任务放到等待执行的异步队列readyAsyncCalls中 3、对等待队列进行一个迭代,判断正在执行的任务数是否大于64 ,相同的host是否大于5 4、正在执行的异步队列中任务数大于64,则不能执行,继续在等待队列等待,如果当前任务的host>5,则进行下一个任务的执行判断 5、将要执行的任务放到正在执行的任务中,并且放到一个临时对列里,调线程池执行 6、线程池执行后,走拦截器,完成后,走回调。 7、拦截器走责任链模式,五大拦截器执行,完成后,回调。 8、完成后,重新触发promoteAndExecute(),进行下一个任务请求
五大拦截器
1、RetryAndFolloeUpInterceptor:重试定向拦截器
判断用户是否取消了拦截器,获得结果后,将状态码去判断是否需要重定向,满足条件重启所有拦截器
2、BrisgeInterceptor:桥接拦截器
对传参后进行的网络处理:Header, Body处理,自动将HTTP协议,请求头,,GZIP压缩,等处理,保存cookie接口去处理
3、CacheInterceptor: 缓存拦截器
请求一个不会改变的资源,读取之前判断当前是否有缓存,有缓存就调缓存直接回调,没有,走连接拦截器
4、Connection:连接拦截器
缓存没有命中, 走连接拦截器,找到与服务器的连接,或者创建一个连接,获取对应的socket流,获取结果后不进行额外处理,直接走请求服务拦截器
5、CallServerInterceptor:请求服务拦截器
拿到连接器后,将数据包装在class发给服务端,得到响应,与服务器通信,向服务器发送数据,解析读取的响应数据,再一步一步返回回去
责任链模式
类似递归调用,由上往下执行,执行后,结果由下往上返回。
最后为了帮助到大家有效率的学好 Android 百大框架知识点,特意整理了一份Android 百大框架进阶滋尿,帮助大家在技术的道路上更进一步,大家有需要的 可以后台私信我回复 666 即可取货!!!
|