一、OkHttp整体流程:
二、异步请求
一次异步请求过程:
//1、创建OkHttpClient
OkHttpClient client = new OkHttpClient.Builder().build();
//2、创建Request
Request request = new Request.Builder()
.url("http://xxx.com")
.build();
//3、创建CallCall call = client.newCall(request);
//4、执行Call的异步方法
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//做一些请求失败的处理
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//做一些请求成功的处理
}
});
1、创建OkHttpClient(OkHttpClient )
OkHttpClient表示了HTTP请求的客户端类, 一般
执行一次new OkHttpClient(),将其作为全局的实例进行保存。
设置OkHttpClient的一些参数,比如超时时间、缓存、拦截等。(通过Build模式创建一个OkHttpClient)
2、创建Request(
Request
)
public final class Request {
private final HttpUrl url;
private final String method;
private final Headers headers;
private final RequestBody body;
private final Object tag;
private volatile CacheControl cacheControl; // Lazily initialized.
}
Request类封装了请求报文信息:请求的Url地址、请求的方法(如GET、POST等)、各种请求头(如Content-Type、Cookie)以及可选的请求体。一般通过内部类Request.Builder的链式调用生成Request对象。
3、创建Call:(Call)
(1)Call接口
public interface Call {
//返回当前Call的Request
Request request();
//同步请求
Response execute() throws IOException;
//异步请求
void enqueue(Callback responseCallback);
//取消请求
void cancel();
//判断是否执行过
boolean isExecuted();
//判断是否取消了
boolean isCanceled();
//内部含有一个内部接口Factory 用于生成
Call interface Factory {
Call newCall(Request request);
}
}
Call是一个接口,主要定义了进行请求和取消请求等的方法 。内部有一个newCall方法,传入一个Request返回一个Call,为下一步进行网络请求做准备。
(2)RealCall
发起请求的真正的类,实现了Call接口
final class RealCall implements Call {
private final OkHttpClient client;
// Guarded by this.
private boolean executed;
volatile boolean canceled;
/** The application's original request unadulterated by redirects or auth headers. */
Request originalRequest;
HttpEngine engine;
protected RealCall(OkHttpClient client, Request originalRequest) {
this.client = client;
this.originalRequest = originalRequest;
}
.....
}
RealCall的创建是通过OkHttpClient的newCall方法
#OkHttpClient
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
4、执行异步请求:
RealCall的enqueue方法
#RealCall
void enqueue(Callback responseCallback) {
synchronized (this) {
//同一个Call只能执行一次,否则会报错。
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
- client.dispatcher():返回的时Dispatcher,Dispatcher是用来管理请求的调度。
- 调用Dispatcher的enqueue方法。
- 传入AsyncCall对象
5、Dispatcher
(1)成员变量
public final class Dispatcher {
//最大并发请求数为64
private int maxRequests = 64;
//每个主机最大请求数为5
private int maxRequestsPerHost = 5;
//线程池
private ExecutorService executorService;
//缓存队列(当runningAsyncCalls的尺寸达到maxRequests参数时(默认64)存储新加的异步请求)
private final Deque<RealCall.AsyncCall> readyAsyncCalls = new ArrayDeque<>();
//正在运行的异步请求队列
private final Deque<RealCall.AsyncCall> runningAsyncCalls = new ArrayDeque<>();
//正在运行的同步请求队列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
}
(2)enqueue方法
#Dispatcher
synchronized void enqueue(AsyncCall call) {
//判断请求时否小于最大值,同一主机的request小于最大值
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call); //加入异步队列
executorService().execute(call); //线程池执行请求
} else {
readyAsyncCalls.add(call); //加入等待队列
}
}
6、
AsyncCall
AsyncCall是RealCall的内部类,继承了NamedRunnable,实际上也是一个Runnable实现类。需要实现的是execute方法
#RealCall.AsyncCall:
@Override
protected void execute() {
boolean signalledCallback = false;
try {
//返回Request对象
Response response = getResponseWithInterceptorChain(forWebSocket);
if (canceled) {
signalledCallback = true;
//失败回调
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
//响应回调
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//请求完成的操作,调用了Dispatch的finished方法
client.dispatcher().finished(this);
}
}
最终获取到了Response对象
7、Response:
Response类封装了响应报文信息:状态吗(200、404等)、响应头(Content-Type、Server等)以及可选的响应体。
(1)通过getResponseWithInterceptorChain获取到Response对象
#RealCall
添加拦截器的操作
private Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
//添加开发者自定义的拦截器
interceptors.addAll(client.interceptors());
//添加失败重连和重定向的拦截器
interceptors.add(retryAndFollowUpInterceptor);
//主要是添加一些请求头和其它信息,同时对返回的响应做一些响应头或其它处理。
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//添加缓存拦截器,根据不同的缓存策略做相应的处理。
interceptors.add(new CacheInterceptor(client.internalCache()));
//添加连接拦截器,与服务器建立Socket连接。
interceptors.add(new ConnectInterceptor(client));
//retryAndFollowUpInterceptor.isForWebSocket() 默认为false
//默认添加网络拦截器
if (!retryAndFollowUpInterceptor.isForWebSocket()) {
interceptors.addAll(client.networkInterceptors());
}
//添加 负责向服务器发送请求数据、从服务器读取响应数据的 CallServerInterceptor
interceptors.add(new CallServerInterceptor(
retryAndFollowUpInterceptor.isForWebSocket()));
// 创建一个RealInterceptorChain,用它来开始处理请求。
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
最终创建并调用了RealInterceptorChain 的proceed方法。
8、RealInterceptorChain :实现Interceptor接口
#
RealInterceptorChain
public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream,
Connection connection) throws IOException {
...
//创建一个新的RealInterceptorChain用于把Request传递给下一个Interceptor去处理
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpStream, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
...
return response;
}
能够把Request依次传递给下一个Interceptor去处理。
每一个Interceptor在发送Request的时候只处理自己那一部分Request,然后通过RealInterceptorChain的带动传递给下一个Interceptor进行处理,最后一个Interceptor发送完请求得到服务器的响应Response。
9、Dispatch的finish方法
请求完成后的操作,finish中调用了promoteCalls方法,
#Dispatch
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
//遍历下一个RealCall
for (Iterator<RealCall.AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
RealCall.AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
//移除
i.remove();
//下一个请求开始
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
移除本次请求,开始线程池中的下一个请求。
三、同步请求:
区别在于调用了RealCall的execute方法。
#RealCall
@Override
public Response execute() throws IOException {
synchronized (this) {
//同一个Call只能执行一次,否则会报错。
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
//Dispatcher.execute(Call call)方法,只是把当前正在执行的Call添加到代表执行中的集合去。
client.dispatcher().executed(this);
//返回响应Response。
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
//对一个Call结束之后做的处理。
client.dispatcher().finished(this);
}
}
总结:主要流程
(1)创建一个OkHttpClient对象,设置拦截、缓存、超时时间等信息。
(2)创建一个Request,包括url、请求方法、请求头、请求体等信息。
(3)创建一个RealCall对象,通过OkHttpClient的newCall方法。内部定义了同步、异步请求、取消请求等方法。
(4)异步请求:通过调用RealCall的enqueue方法,内部通过调用Dispatcher的enqueue方法,具体是调用AsyncCall中的execute方法。
同步请求:通过调用RealCall的execute方法进行处理。
(5)通过Interceptor拦截器进行链式的拦截处理,具体实现是RealInterceptorChain
(6)通过调用RealInterceptorChain的proceed返回响应Response。
(7)在Dispatcher中移除本次请求,开始下次请求。
参考文章: