OkHttp 源码分析
程序员文章站
2022-07-13 10:58:36
...
OkHttp 使用代码实例
private static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
// 同步调用
Response response = client.newCall(request).execute();
// 异步调用
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
return response.body().string();
}
源码分析
先来看 new OkHttpClient()
public OkHttpClient() {
this(new Builder());
}
public Builder() {
// 创建了 Dispatcher 对象
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;
}
然后 clien.newCall(request) 创建了 RealCall 对象,这也是 OkHttp 中一个重要的类,先来分析异步执行的源码吧,因为同步执行跟异步的后半段没什么区别了。
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
// 执行 dispatcher 的 enqueue 方法,dispatcher 是在创建 HttpClient 对象时 new 的。注意这里传过去是的 new AsyncCall(responseCallback)
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
AsyncCall 是实现了 NamedRunnable
public abstract class NamedRunnable implements Runnable {
// ...
@Override public final void run() {
// ...
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
可以看到就是实现的 Runnable 接口,如果在一个线程里执行,执行的就是 execute 方法。再接着看 dispatcher 的 enqueue 方法
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
// 添加到执行队列
runningAsyncCalls.add(call);
// 在子线程执行方法,executorService 就是创建了线程池。
executorService().execute(call);
} else {
// 添加到等待队列
readyAsyncCalls.add(call);
}
}
AsyncCall 执行的是 execute 方法,下面接着看这里
@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 {
// 从 dispatcher 的运行队列中清除该 Runnable
client.dispatcher().finished(this);
}
}
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
// 添加自己定义的 interceptor
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);
}
来一个链式调用的例子吧,
// 实际执行
public static void main(String[] args) {
List<Interceptor> interceptors = new ArrayList<>();
interceptors.add(new Interceptor1());
interceptors.add(new Interceptor2());
InterceptorChain chain = new InterceptorChain(interceptors, 0);
chain.proceed();
}
// 执行链
public class InterceptorChain {
private List<Interceptor> interceptors;
private int index;
public InterceptorChain(List<Interceptor> interceptors, int index) {
this.interceptors = interceptors;
this.index = index;
}
public void proceed() {
if (index >= interceptors.size()) {
System.out.println("调用完");
return;
}
InterceptorChain chain = new InterceptorChain(interceptors, index+1);
Interceptor interceptor = interceptors.get(index);
interceptor.proceed(chain);
}
}
// Interceptor
public interface Interceptor {
String proceed(InterceptorChain chain);
}
public class Interceptor1 implements Interceptor {
@Override
public String proceed(InterceptorChain chain) {
System.out.println("Interceptor1 start");
chain.proceed();
System.out.println("Interceptor1 end");
return "Interceptor1";
}
}
public class Interceptor2 implements Interceptor {
@Override
public String proceed(InterceptorChain chain) {
System.out.println("Interceptor2 start");
chain.proceed();
System.out.println("Interceptor2 end");
return "Interceptor2";
}
}
最终的执行结果是:
Interceptor1 start
Interceptor2 start
调用完
Interceptor2 end
Interceptor1 end
可以看到 1 先执行,在 1 里面调 2 的执行,2 执行完的返回结果,1 可以再进行处理。
来一张图解释下吧
OkHttp 的调用过程用下面的图来简介一下
上一篇: okhttp简单封装
下一篇: OKHttp源码解析(一)