通过Okhttp使用流程,一步一步查看源码如何实现!
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;
//连接池 客户端 --服务端 中间的连接 称之为 connection 而 所有的连接都是放在连接池中的即: // ConnectionPool
// 当请求的 URL相同时 可以选择复用
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
public Builder() {
//默认请求方式
this.method = "GET";
//头部信息
this.headers = new Headers.Builder();
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
//把Builder封装好的 对象传递给 Request
return new Request(this);
}
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;
}
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
//第一步创建好的OkHttpClient
this.client = client;
//第二步创建好的 Request
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
//重定向拦截器
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
以上步骤 是同步和异步请求相同的部分
@Override public Response execute() throws IOException {
//同步代码块
synchronized (this) {
//同一个http请求只能执行一次
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
//捕捉异常
captureCallStackTrace();
//开启请求时开启listener
eventListener.callStart(this);
try {
//通过 OkHttpClient 获得 分发器 ,并调用分发器中的 executed 方法 ①
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);
}
}
/** Used by {@code Call#execute} to signal it is in-flight. */
synchronized void executed(RealCall call) {
//加入队列 runningSyncCalls ②
runningSyncCalls.add(call);
}
/** 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<>();
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
//同一个http请求只能执行一次
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//通过 OkHttpClient 获得 分发器 ,并调用分发器中的 enqueue 方法 ① 传入 AsyncCall ②
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
synchronized void enqueue(AsyncCall call) {
//首先判断当前 正在请求的数是否小于 最大请求数 private int maxRequests = 64;
// 并且 当前网络请求的 Host是否小于 maxRequestsPerHost private int maxRequestsPerHost = 5;
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
//条件满足 加入到正在执行的异步请求队列当中
runningAsyncCalls.add(call);
//通过线程 executorService ①① 池执行 call请求
executorService().execute(call);
} else {
//如果条件不满足 就把请求加入到 异步就绪队列 等待条件满足执行 call请求
readyAsyncCalls.add(call);
}
}
//通过 synchronized 保证对象 是单例
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;
}
final class AsyncCall extends NamedRunnable
public abstract class NamedRunnable implements Runnable
//就是 一个 Runnable run()方法②①
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
//真正执行操作的方法 execute ②①①
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
@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 {
//回收请求 finished②①①①
client.dispatcher().finished(this);
}
}
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!");
// promoteCalls() 调整任务队列
if (promoteCalls) promoteCalls();
//异步进入此方法
//重新赋值 正在执行的请求数 runningCallsCount() == runningAsyncCalls.size() + //runningSyncCalls.size();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
//空闲时执行空闲回调
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
为维护请求的状态,并维护一个线程池,用于执行请求
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.
}
}
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()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//创建 Chain 即链
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
// 调用 proceed()发起网络请求
return chain.proceed(originalRequest);
}
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.httpCodec != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
创建下一个拦截器
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
//放入 intercept 实现 这个方法是5个拦截器
//RetryAndFollowUpInterceptor
//BridgeInterceptor
//CacheInterceptor
//ConnectInterceptor
//CallServerInterceptor
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
RetryAndFollowUpInterceptor负责失败重试以及重定向。
RetryAndFollowUpInterceptor的作用就是处理了一些连接异常以及重定向。
BridgeInterceptor就跟它的名字那样,它是一个连接桥,它负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应。
转换的过程就是添加一些服务端需要的header信息。
在Request阶段配置用户信息,并添加一些请求头。在Response阶段,进行gzip解压。
1.根据策略,不使用网络,又没有缓存的直接报错,并返回错误码504。
2.根据策略,不使用网络,有缓存的直接返回。
3.前面两个都没有返回,继续执行下一个Interceptor,即ConnectInterceptor。
4.接收到网络结果,如果响应code式304,则使用缓存,返回缓存结果。
5.读取网络结果。
6.对数据进行缓存。
7.返回网络读取的结果。
在RetryAndFollowUpInterceptor里初始化了一个StreamAllocation对象,我们说在这个StreamAllocation对象里初始化了一个Socket对象用来做连接,但是并没有 真正的连接,等到处理完hader和缓存信息之后,才调用ConnectInterceptor来进行真正的连接。
这是链中的最后一个拦截器。 它会对服务器进行网络请求
我们通过ConnectInterceptor已经连接到服务器了,接下来我们就是写入请求数据以及读出返回数据了。整个流程:
写入请求头
写入请求体
读取响应头
读取响应体
Okhttp源码实现逻辑还是非常容易理解的,如果不理解,多看几遍就Ok了!设计的非常精妙,从中可以学习到许多编程思想。