okhttp官方地址: https://square.github.io/okhttp/
okhttp的使用方法:
官方demo给出 直接new出一个OkHttpClient对象
//初始化OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient();
//初始化Request
Request request = new Request.Builder().url("url").build();
//进行网络请求
//同步请求
Response response = okHttpClient.newCall(request).execute();
//异步请求
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {}
});
然后我们查看一下OkHttpClient源码,我们发现OkHttpClient在设计时使用了Builder模式,Builder模式一般用于构建对象时,里面存在很多复杂参数时采用。而在Android源码中AlertDialog就是使用Builder来构建的对象。现在回头来看OkHttp源码:
public OkHttpClient() {
this(new Builder());
}
public static final class Builder {
Dispatcher dispatcher;
Proxy proxy;
List<Protocol> protocols;
····· 省略部分参数
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
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是OkHttp的静态内部类,在Builder类中初始化话了一堆参数。
接下来初始化Request对象,我们发现其实它也是使用了Builder模式构建的
/**
* Sets the URL target of this request.
*
* @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this
* exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs.
*/
public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");
// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}
return url(HttpUrl.get(url));
}
这里主要还是进行URL转换,除了添加url还有其他参数的设置,
接下来我们看看OkHttp的重点:网络请求
不管是同步还是异步都调用了newCall方法,所以来看看newCall到底做了什么。首先newCall通过静态方法创建了一个RealCall对象(不同版本可能不一样,有的是直接new的,Call是一个接口,并提供了一个内部接口Factory和一些请求方法,RealCall是其实现类),然后添加了eventListener参数,而该参数的创建代码已经贴出,具体自行查看。关于EventListener这个类主要还是用来监听网络请求的一些回调方法。
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
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;
}
public Builder eventListenerFactory(EventListener.Factory eventListenerFactory) {
if (eventListenerFactory == null) {
throw new NullPointerException("eventListenerFactory == null");
}
this.eventListenerFactory = eventListenerFactory;
return this;
}
public Builder eventListener(EventListener eventListener) {
if (eventListener == null) throw new NullPointerException("eventListener == null");
this.eventListenerFactory = EventListener.factory(eventListener);
return this;
}
static EventListener.Factory factory(final EventListener listener) {
return new EventListener.Factory() {
public EventListener create(Call call) {
return listener;
}
};
}
public abstract class EventListener {
public static final EventListener NONE = new EventListener() {
};
static EventListener.Factory factory(final EventListener listener) {
return new EventListener.Factory() {
public EventListener create(Call call) {
return listener;
}
};
}
省略部分代码
接下来我们来看看 execute方法和enqueue方法:
首先来看看execute同步方法:内部主要调用了getResponseWithInterceptorChain()方法返回Response,该方法内部主要是构建了一系列的拦截器然后返回请求的结果,当中核心代码就是
responseCallback.onFailure(RealCall.this, new IOException(“Canceled”));和 responseCallback.onResponse(RealCall.this, response);一个是请求失败一个是请求成功。最终调用client.dispatcher().finished(this);
//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 {
client.dispatcher().finished(this);
}
}
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));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
接下来我们看看enqueue方法:
首先RealCall中的enqueue方法当中会通过OkHttpClient获取Dispatcher,而且我们发现不管是异步还是同步都调用了client.dispatcher(),那么这个Dispatcher到底是什么我们先来说说:我们发现当中有个ExecutorService,这个不就是我们经常创建线程池的类么,所以Dispatcher就是线程池的封装类,而且通过executorService()方法创建了一个单例线程池,然后看看Dispatcher中的enqueue方法,首先进行了判断如果正在执行请求的队列的请求数量小于maxRequests并且主机运行调用的数量小于主机的最大请求数量时,那么将该请求添加到正在执行请求的队列中,然后交给线程池处理,否则的话添加到正在准备的队列当中。那么当中的AsyncCall又是个什么鬼呢?下面继续说,
//RealCall当中enqueue方法
@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));
}
//Dispatcher中的一些参数和enqueue方法
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
/** 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<>();
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
/** Returns the number of running calls that share a host with {@code call}. */
private int runningCallsForHost(AsyncCall call) {
int result = 0;
for (AsyncCall c : runningAsyncCalls) {
if (c.get().forWebSocket) continue;
if (c.host().equals(call.host())) result++;
}
return result;
}
//Dispatcher中的executorService
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;
}
看源码发现 AsyncCall是RealCall的内部类,继承NamedRunnable,NamedRunnable又实现了Runnable接口,在它的run方法中又调用了execute方法,而这个execute方法跟同步请求的execute方法最终执行的是同一个方法,也就是最终还是通过getResponseWithInterceptorChain()方法返回Response。
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void 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 {
client.dispatcher().finished(this);
}
}
好了,大致的整体流程就是这样,还有就是OkHttpClient中添加一些拦截器什么的,后续有时间在更新。如果文中存在误导性的错误,欢迎大家纠正交流。