先看一下平常我们是如和使用okHttp的 下面是官网上例子
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
总共分三部,下面咱们排着个解析一下
第一步
OkHttpClient client = new OkHttpClient();
来看一下这个okHttpClient这个类是干吗的
public OkHttpClient() {
this(new Builder());
}
在new OkHttpClient的时候 其实是创建了一个 Build对象,(Build模式,Build是一个内部类,常用于先对Build类进行赋值,最后再生成主类)
来看一下Build类
//OkHttpClient类
public static final class Builder {
Dispatcher dispatcher;//任务调度类
@Nullable Proxy proxy;//代理类
List<Protocol> protocols;//协议类集合
List<ConnectionSpec> connectionSpecs;//连接规格集合
final List<Interceptor> interceptors = new ArrayList<>();//拦截器集合
final List<Interceptor> networkInterceptors = new ArrayList<>();//网络拦截器
EventListener.Factory eventListenerFactory;//事件监听工厂类
ProxySelector proxySelector;
CookieJar cookieJar;
@Nullable Cache cache;
@Nullable InternalCache internalCache;
SocketFactory socketFactory;
@Nullable SSLSocketFactory sslSocketFactory;
@Nullable CertificateChainCleaner certificateChainCleaner;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator;
Authenticator authenticator;
ConnectionPool connectionPool;//连接池
Dns dns;
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
int connectTimeout;//连接时间
int readTimeout;//读取时间
int writeTimeout;//等待时间
int pingInterval;
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;协议
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
Builder(OkHttpClient okHttpClient) {
this.dispatcher = okHttpClient.dispatcher;
this.proxy = okHttpClient.proxy;
this.protocols = okHttpClient.protocols;
this.connectionSpecs = okHttpClient.connectionSpecs;
this.interceptors.addAll(okHttpClient.interceptors);
this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
this.eventListenerFactory = okHttpClient.eventListenerFactory;
this.proxySelector = okHttpClient.proxySelector;
this.cookieJar = okHttpClient.cookieJar;
this.internalCache = okHttpClient.internalCache;
this.cache = okHttpClient.cache;
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.certificateChainCleaner = okHttpClient.certificateChainCleaner;
this.hostnameVerifier = okHttpClient.hostnameVerifier;
this.certificatePinner = okHttpClient.certificatePinner;
this.proxyAuthenticator = okHttpClient.proxyAuthenticator;
this.authenticator = okHttpClient.authenticator;
this.connectionPool = okHttpClient.connectionPool;
this.dns = okHttpClient.dns;
this.followSslRedirects = okHttpClient.followSslRedirects;
this.followRedirects = okHttpClient.followRedirects;
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
this.connectTimeout = okHttpClient.connectTimeout;
this.readTimeout = okHttpClient.readTimeout;
this.writeTimeout = okHttpClient.writeTimeout;
this.pingInterval = okHttpClient.pingInterval;
}
看起来很多 其实就是给属性赋值而已,
Builder()构造方法 是自己给属性赋值,
Builder(OkHttpClient okHttpClient)是利用OkHttpClient 对象来赋值我们重点看参数,重要的我已经写注解了,直接看属性
可以看出OkHttpClient类 是对请求的一个封装类,
dispatch和interrupt很重要 下面会讲到
接下来看第二步
Request request = new Request.Builder()
.url(url)
.build();
我们来看Requet类
//Request类
public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Object tag;
private volatile CacheControl cacheControl; // Lazily initialized.
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tag = builder.tag != null ? builder.tag : this;
}
很明显 这个类 是一个请求的类,包含了请求地址,请求头,请求方式
接下来看第三步
Response response = client.newCall(request).execute();
这时候 我们有了执行请求的OkHttpClient类,有了封装请求的Request类,我们就要开始执行请求了,
有两个方法 我们分别来看一下,newCall和execut,
newCall:
//OKHttpClient类
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
可以看出 返回了一个RealCall,来看一下RealCall这个类
//RealCall类
final class RealCall implements Call {
final OkHttpClient client;
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
/**
* There is a cycle between the {@link Call} and {@link EventListener} that makes this awkward.
* This will be set after we create the call instance then create the event listener instance.
*/
private EventListener eventListener;
/** The application's original request unadulterated by redirects or auth headers. */
final Request originalRequest;
final boolean forWebSocket;
// Guarded by this.
private boolean executed;
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
可以看出 realCall实现了call接口,并且这个类持有 OkHttpCall和Requset ,
那么在执行okHttpClient.newCall(request). execute/enqueue的时候 其实是执行了RealCall类的execute/enqueue
接下来我们详细看一下OkHttpClent的dispatch
//dispatch类
public final class Dispatcher {
private int maxRequests = 64;//最大并发请求数量
private int maxRequestsPerHost = 5;//每个主机的最大请求数
private @Nullable Runnable idleCallback;//貌似是回掉类
/** Executes calls. Created lazily. */
private @Nullable ExecutorService executorService;//线程池
/** Ready async calls in the order they'll be run. */
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//将要运行的异步队列
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//正在运行的异步队列
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//正在运行同步队列
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
//在这一步可以看出来executeService其实就是一个线程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
可以看出 dispatch是执行请求的封装类,
接下来我们看一下他是如和进行请求的,
好 现在我们先捋一下吧还是,
我们首先我们创建了Okhttpclient (里面有一个dispatch和executeService)和 request,
我们在调用OKHttpClient。newCall(request)的时候
其实是new出来一个一个RealCall,RealCall实现了Call接口,
在执行RealCall.execute/enqueue的时候,其实是将RealCall给了dispatch,
dispatch将realCall传给了executeService,
至此 我们已经将请求添加到线程池里了,那么我们是在什么时候执行呢
分两种情况 一种是同步请求 一种是异步请求,
先看同步的吧
//RealCall类
@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);//将请求在队列中移除
}
}
看一下dispatch的executed
//dispatch类
/** Used by {@code Call#execute} to signal it is in-flight. */
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
其实就是将请求添加到正在运行的同步队列中
我们来看一下getResponseWithInterruptorChain,
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
//创建一个拦截器集合
List<Interceptor> interceptors = new ArrayList<>();
//假如OKHttpClient中的拦截器,我们自己定义的拦截器也是在这个时候添加的
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());
return chain.proceed(originalRequest);
}
看一下dispatch的finished方法
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");//注释1
if (promoteCalls) promoteCalls();//注释2
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
//runingCallsCount是正在运行的请求数量
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
看注1处 将当前请求移除队列,因为promoteCalls是false 所以并不会执行promoteCalls,不过这个方法很重要,下面会讲到,
同步的分析完了 我们看一下异步的,同样 也是从realCall的enqueue开始
//realcall类
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));//最终也是执行了dispatch的enqeue
}
套路是一样的,看dispatch的enqueue
//dispatch类
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
和同步不一样的地方是 同步是RealCall异步是AsyncCall(是RealCall的一个内部类)
executeService>execute(Call)这里其实是执行的call的execute方法,
我们来看一下
//AsyncCall类
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();//重点看这里,
if (retryAndFollowUpInterceptor.isCanceled()) {
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 {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);//重点还有这里
}
}
虽然说异步call是AsyncCall 但是执行请求和将请求移除队列 还是用的RealCall里的方法
getResponseWithInterceptorChain刚刚已经解释过了 其实就是执行请求 并得到返回的结果
我们把重点放到clinet.dispatcher.finished(this);上来
//dispatch类
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
//dispatch类
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");//移除当前的请求
if (promoteCalls) promoteCalls();//这个是promoteCalls为true
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
移除当前的请求,
这个时候promoteCalls为true,所以会执行promoteCalls
//dispatch类
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
可以看出,如果异步队列中还有任务 则调用executeService.execut(call)来执行下一个任务
好了 大致就是这样,