OkHttp源码的samples的简单使用的示例:
public static void main(String... args) throws Exception{
OkHttpClient client=new OkHttpClient();
// Create request for remote resource.
Request request=new Request.Builder()
.url(ENDPOINT)
.build();
// Execute the request and retrieve the response.
Response response=client.newCall(request).execute();
// Deserialize HTTP response to concrete type.
ResponseBody body=response.body();
Listcontributors=CONTRIBUTORS_JSON_ADAPTER.fromJson(body.source());
body.close();
......
}
静态常量
OkHttpClient开始就定义了两个静态常量,这两个常量是与协议相关分别是DEFAULT_CONNECTION_SPECS和DEFAULT_PROTOCOLS。
静态代码块
接下来看OkHttpClient的static代码块主要就是创建了一个Internal的内部类对象。
接口
OkHttpClient实现了三个接口,分别是Cloneable,Call.Factory,WebSocket.Factory
重点在Call.Factory接口上,Call该接口的实例就是我么去执行请求网络数据的对象,
Call中的主要方法
/** 返回该Call创建的Request请求对象 */
Request request();
/** 同步执行请求网络数据,返回服务端响应结果*/
Response execute()throwsIOException;
/** 异步执行请求网络数据的回调方法*/
void enqueue(Callback responseCallback);
/** 取消网络请求*/
void cancel();
/** 判断网络请求是否被执行了*/
boolean isExecuted();
/** 判断网络请求是否被取消了*/
boolean isCanceled();
/**clone该方法是Cloneable接口中的方法,意义在于创建一个相同的请求对象*/
Call clone();
/**Factory内部接口就是创建Call的工厂接口,该接口定义的方法newCall需要传入Request对象*/
interface Factory{
Call newCall(Request request);
}
成员变量
最重要的就是OkHttpClient,该类的成员变量中6个成员变量进行重点说明的
final Dispatcher dispatcher;
final List interceptors;
final List networkInterceptors;
final EventListener.Factory eventListenerFactory;
final @Nullable Cache cache;
final @Nullable InternalCache internalCache;
1、同步请求过程解析
Response response=client.newCall(request).execute(); 这句代码执行过程:
(1)client.newCall(request)
第一步:上面提到OkHttpClient的三个接口中有个Factory内部接口(创建Call的工厂接口),而Call对象有个实现类RealCall,其实newCall方法是RealCall执行自己的newRealCall方法创建了一个RealCall实例,该方法三个参数如下:
*@param client OkHttpClient对象
*@param originalRequest 之前传入的那个原始请求对象
*@param forWebSocket 是否是WebSocket
RealCall call=newRealCall(client,originalRequest,forWebSocket);
第二步:上面提到OkHttpClient的6个成员变量中有个EventListener.Factory eventListenerFactory对象(也是个工厂接口,内部定义了一个create方法用于创建EventListener对象),上一步传入了OkHttpClient对象,该对象已经创建完了eventListenerFactory实例,所以拿到该实例传入call对象创建EventListener对象。
抽象类EventListener中有一大堆的网络连接的监听方法
call.eventListener=client.eventListenerFactory().create(call);
最后返回当前的Call对象
(2)call.execute()
@Override
publicResponse execute()throwsIOException{
synchronized(this) {
if(executed)throw newIllegalStateException("Already Executed");
executed=true;
}
captureCallStackTrace();
try{
client.dispatcher().executed(this);
Response result=getResponseWithInterceptorChain();
if(result==null)throw newIOException("Canceled");
returnresult;
}finally{
client.dispatcher().finished(this);
}
}
(2.1)call中的execute方法中的client.dispatcher().executed(this);
由于execute是同步执行网络请求所以要用关键字synchronized,
synchronized(this) {
if(executed)throw newIllegalStateException("Already Executed");
executed=true;
}
之后再执行captureCallStackTrace()方法,放入堆栈进行追踪捕捉。
client.dispatcher()是获得上面OkHttpClient的成员变量Dispatcher dispatcher,注意啦Dispatcher中的方法基本都是同步,用的Synchronized修饰的方法。为了分析清楚这里插一段Dispatcher的说明。
Dispatcher中维护着执行发送请求的线程池,所有的请求都是放在请求队列中的总共有三个队列readyAsyncCalls(准备的异步请求队列),runningAsyncCalls(正在在执行的异步请求还包括被中断的),runningSyncCalls(正在在执行的异步请求还包括被中断的)
private final Deque<AsyncCall> readyAsyncCalls=newArrayDeque<>();
private final Deque<AsyncCall> runningAsyncCalls=newArrayDeque<>();
private final Deque<RealCall> runningSyncCalls=newArrayDeque<>();
RealCall和AsyncCall的关系通过Dispatcher类的导入代码可以看出
import okhttp3.RealCall.AsyncCall; // AsyncCall其实就是RealCall的内部类
具体实现如下:
final class AsyncCall extends NamedRunnable{
private final Callback responseCallback;
// 构造时需要传入一个Callback接口,也就是返回给我们成功失败的回调方法
AsyncCall(Callback responseCallback) {
super("OkHttp %s",redactedUrl());
this.responseCallback=responseCallback;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
@Override
protected void execute() {
boolean signalledCallback=false;
try{
Response response=getResponseWithInterceptorChain();
if(retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback=true;
responseCallback.onFailure(RealCall.this,newIOException("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{
client.dispatcher().finished(this);
}
}
}
dispatcher中erexecuted方法的具体实现
// 加入同步执行队列
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
(2.2)Response result=getResponseWithInterceptorChain();
下面回过头去看RealCall的execute方法中client.dispatcher().executed(this);执行结束后的代码Response result=getResponseWithInterceptorChain();
为了分析清楚这里插一段Interceptor的说明
Response getResponseWithInterceptorChain()throwsIOException{
//创建一个存放拦截器的集合,最后传入 newRealInterceptorChain对象中
List<Intercepter> interceptors=newArrayList<>();
// client.interceptors() (自定义的拦截器, 在call api的前的拦截) - > //retryAndFollowUpInterceptor (实现请求重试)
interceptors.addAll(client.interceptors());
// 重定向拦截器
interceptors.add(retryAndFollowUpInterceptor);
// 桥接拦截器(处理header 、cookie 等)
interceptors.add(newBridgeInterceptor(client.cookieJar()));
// 缓存拦截器(处理 cache)
interceptors.add(newCacheInterceptor(client.internalCache()));
// 连接拦截器(负责建立连接)
interceptors.add(newConnectInterceptor(client));
if(!forWebSocket) {
// 自定义网络拦截器(此时已建立连接)
interceptors.addAll(client.networkInterceptors());
}
// 服务请求拦截器(发起请求、接收响应)
interceptors.add(newCallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors,null,null,null,0,originalRequest,this,eventListener); return chain.proceed(originalRequest);
}
上面的RealInterceptorChain方法具体实现。在RealCall里的getResponseWithInterceptorChain方法里,创建了一个RealInterceptorChain对象,调用proceed(),在interceptor的intercept()方法里又调用proceed(),明显形成了一个递归,像链表一下一个一个递归传递并且做相应的拦截处理。
RealInterceptorChain next=newRealInterceptorChain(interceptors,streamAllocation,httpCodec,
connection,index+1,request,call,eventListener);
Interceptor interceptor=interceptors.get(index);
Response response=interceptor.intercept(next);
最后一个拦截器返回处理的Response,也就是服务器端返回的结果,并且在代码中加了许多的判断如:this.httpCodec!=null 意思就是还没有拦截链执行完。interceptor必须执行一次proceed()方法,否则会抛异常。
RealInterceptorChain + Interceptor实现了装饰器模式,实现了请求/响应的串式或流式处理。只不过内层装饰器不是外层装饰器的成员变量,而是接口方法中创建的临时变量。
在ConnectInterceptor之后的拦截器必须满足:request的url要一致,interceptor必须执行一次proceed()。这样子做是为了保证递推的正常运作。而对与client.interceptors是在ConnectInterceptor之前的拦截器,可以不用必须执行一次proceed()。可以实现直接返回虚拟的response用于是测试等功能。
这几个Interceptor的职责:
RetryAndFollowUpInterceptor --->创建StreamAllocation对象,处理http的redirect,出错重试。对后续Interceptor的执行的影响:修改request及StreamAllocation。
BridgeInterceptor-------------->补全缺失的一些http header。对后续Interceptor的执行的影响:修改request。
CacheInterceptor-------------->处理http缓存。对后续Interceptor的执行的影响:若缓存中有所需请求的响应,则后续Interceptor不再执行。
ConnectInterceptor------------>借助于前面分配的StreamAllocation对象建立与服务器之间的连接,并选定交互所用的协议是HTTP 1.1还是HTTP 2。对后续Interceptor的执行的影响:创建了httpStream和connection。
CallServerInterceptor----------->处理IO,与服务器进行数据交换。对后续Interceptor的执行的影响:为Interceptor链中的最后一个Interceptor,没有后续Interceptor
(2.3)client.dispatcher().finished(this);
dispatcher中finish方法的具体实现(注意第三个参数的差别)
/** Used by {@codeCall #execute} to signal completion.同步方法 */
void finished(RealCall call) {
finished(runningSyncCalls,call,false);
}
/** Used by {@codeAsyncCall#run} to signal completion. 异步方法*/
void finished(AsyncCall call) {
finished(runningAsyncCalls,call,true);
}
上面的finished(runningAsyncCalls,call,true);方法实现如下:
private void finished(Dequecalls,T call,boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized(this) {
if (!calls.remove(call) ) throw newAssertionError("Call wasn't in-flight!");
if(promoteCalls) promoteCalls(); // 异步Call数量多时需要维护队列,而不是立即执.行,所以要加入到runningAsyncCalls中
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if(runningCallsCount==0&&idleCallback!=null) {
idleCallback.run();
}
}
上面promoteCalls方法的具体实现如下:
private int maxRequests=64;
private int maxRequestsPerHost=5;
private void promoteCalls() {
if(runningAsyncCalls.size()>=maxRequests) return;// 已经达到最大容器.
if ( readyAsyncCalls.isEmpty() ) return; // 队列为空
for(Iterator i=readyAsyncCalls.iterator();i.hasNext();) { // 遍历取出
AsyncCall call=i.next();
// 当正在执行的任务总数及相同host下的任务数小于最大值时,直接执行当前请求,而任务数超过限定时,将其加入等待队列。
if ( runningCallsForHost(call) < maxRequestsPerHost ){
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
}
if ( runningAsyncCalls.size()>=maxRequests ) return;// Reached max capacity.
}
}
还可以通setMaxRequests()设置同时允许执行的最大请求数,以及setMaxRequestsPerHost()设置相同host下最多运行的请求数。从源码中看出OkHttpClient用了许多的Budiler设计模式,几个重要的类Response、Request、OkHttpClient。
2、异步请求过程解析
RealCall的enqueue方法,其中遇到的大部分方法在同步请求中有分析就不赘述了。主要讲一下异步网络请求的流程
@Override
public voidenqueue(Callback responseCallback) {
synchronized(this) {
if(executed)throw newIllegalStateException("Already Executed");
executed=true;
}
captureCallStackTrace();
client.dispatcher().enqueue(newAsyncCall(responseCallback));
}
上面client.dispatcher().enqueue(newAsyncCall(responseCallback));中Dispatcher的enqueue方法
synchronized void enqueue(AsyncCall call) {
// 如果正在执行异步请求的队列没有超过最大请求数量,并且有没有超过每个主机允许的最大访问量
// 就将请求加入到正在执行异步请求的队列中,否则就加入到准备异步请求的队列中去
if(runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost
runningAsyncCalls.add(call);
executorService().execute(call);
}else{
readyAsyncCalls.add(call);
}
异步请求返回是通过接口回调的具体实现如下:
final classAsyncCallextendsNamedRunnable{
private finalCallback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s",redactedUrl());
this.responseCallback=responseCallback;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
@Override
protected voidexecute() {
booleansignalledCallback=false;
try{
Response response=getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled() ) {
signalledCallback=true;
responseCallback.onFailure(RealCall.this,newIOException("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{
client.dispatcher().finished(this);
}
}
}
网友评论