文章目录
阅读分析
在阅读本篇文章时,请对比Okhttp源码。基于3.6版本Okhttp.
Okhttp使用实例
//创建client
OkHttpClient client = new OkHttpClient();
//创建request请求
Request request = new Request.Builder().url("http://www.baidu.com") .build();
//发起请求
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
System.out.println("成功");
}
} catch (IOException e) {
e.printStackTrace();
}
创建Okhttp实例对象
public OkHttpClient() {
this(new Builder());
}
OkHttpClient(Builder builder) {
//网络请求调度器
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
//默认支持的Http协议版本
this.protocols = builder.protocols;
......//省略代码
} }
创建Okhttp实例时使用了建造者模式.在创造Okhttp实例对象时,Okhttp配置了很多的参数,dispather任务调度器等
创建Request对象
Request也使用了建造者模式,里面配置了请求的header body method url。
创建Call
调用client.newCall(request);时最终会调用RealCall里面的newCall方法。
RealCall是Call的实现类。RealCall构造方法中创造了重定向拦截器。返回一个RealCall实例
发起请求
同步请求execute()
@Override
public Response execute() throws IOException {
synchronized (this) {
//判断同步请求是否执行过,如果执行过抛出异常
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
//打开监听事件
eventListener.callStart(this);
try {
//将请求添加到任务队列
client.dispatcher().executed(this);
//通过拦截器发起请求
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
//结束请求
client.dispatcher().finished(this);
}
}
异步请求enqueen()
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//创建AsyncCall,最终异步请求回调会在AsyncCall中执行
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
任务调度器Dispatcher
synchronized void enqueue(AsyncCall call) {
//判断异步请求个数是否小于最大个数,同一个host的请求个数是否小于最大允许个数
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
//将请求添加到异步请求队列
runningAsyncCalls.add(call);
//获取一个线程池,执行call的回调,最终在RealCall的AsyncCall的run方法中执行真正的回调请求。
//在execute方法中执行getWritewithResponse 通过拦截器链发起请求
executorService().execute(call);
} else {
//将请求添加到异步等待队列
readyAsyncCalls.add(call);
}
}
任务调度器里面定义了最大请求数和同一个host允许的最大请求数。
管理了三个队列
readyAsyncCalls 等待被执行的异步请求队列
runningAsynCalls 正在执行的异步请求队列
runningSyncCalls 正在运行的同步请求队列,同步请求会将请求直接添加在队列中。
实现多线程调度并发:
1 dispatcher内部创建了一个线程池。类似缓存线程,如果当前线程池饱和回调用addWorker(command, false)创建新的线程,
所以实际上并发策略是通过dispatcher来实现
2调度策略。
1:设置了最大的线程数,和同一个host下的最大数
2: 等待队列中的请求什么时候执行。在AsyncCalls执行结束会执行dispatcher方法,最终会遍历等待队列,如果运行队列符合
小于64并且host小于5,等待队列不为空,将请求从等待队列中移除,调用线程池的executorService().execute(call);的方法。
拦截器
//Okhttp通过拦截器链发起请求
Response getResponseWithInterceptorChain() throws IOException {
// 创建拦截器集合
List<Interceptor> interceptors = new ArrayList<>();
//自定义拦截器
interceptors.addAll(client.interceptors());
//重定向拦截器
interceptors.add(retryAndFollowUpInterceptor);
//桥接连接器
interceptors.add(new BridgeInterceptor(client.cookieJar()));
/缓存拦截器
interceptors.add(new CacheInterceptor(client.internalCache()));
//连接拦截器
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
网络传输拦截器
interceptors.add(new CallServerInterceptor(forWebSocket));
//生成拦截器链,
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
//开启链式调用,通过proceed方法一次调用每一个拦截器。
return chain.proceed(originalRequest);
}
重定向拦截器retryAndFollowUpInterceptor
重定向流程:通过flowwUp根据响应吗处理Request请求,如果request为空返回Reponse.不为空则进行重定向。
桥接连接器BridgeInterInterceptor
将用户请求request转换为可以进行网络访问的请求。设置内容的长度,cookie,编码方式,请求头等相关信息。
调用procced方法将请求传递给下一个拦截器。将response返回给上一个拦截器
CacheInterceptor缓存拦截器
1缓存拦截器,需要穿进去一个缓存策略。