OkHttp到Retrofit + OkHttp再到hongyang大神的OkHttpUtils,OkHttp对于android的网络框架至关重要,之前在博客中有对OkHttp2.x 到OkHttp3.x使用及其源码进行过剖析
okhttp 2.x 用法/封装
Okhttp3使用 + 源码完全解析
但是相对于其他框架OkHttp的源码较多,需要有清晰的逻辑线来理解,当然前提是建立在OkHttp的熟练使用之上,下面是OkHttp官网:
Okhttp官网
首先来看OKHttp的一个简单的源码图解
OkHttpClient
- 其实在OkHttp中OkHttpClient是一个控制的角色;首先来看OkHttp的Builder类:
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;
}
初始化调度器,超时时间,复连接池,相关枚举,在其成员变量中还会初始化两个不可变的域来存放拦截器(在OkHttp中拦截器比较重要,下文会着重去解释):
final List<Interceptor> interceptors = new ArrayList<>();
final List<Interceptor> networkInterceptors = new ArrayList<>();
- 接着可以根据需求来设置相关的属性:
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new NetInterceptor())
.build();
这是一个构建者,不必多说,提一点在开发使用中可以自定义添加拦截器,在OkHttp中网络请求会在拦截器中返回reponse响应,所以根据需求,在拦截器中可以打印请求日志,或者修改请求头,或者响应头等操作;
public class NetInterceptor implements Interceptor {
//拦截网络
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//打印请求头 请求体
//添加修改请求head等
....
Response response = chain.proceed(request);
//添加修改响应头等
....
return response;
}
}
Request
- 在OkHttp中request同样提供构建者来进行初始化成员(url,head,body,method等);
这里顺带提一下在源码中构建者使用居多,主要是考虑可读性和线程安全,有兴趣可以看以下博文:
多个构造器时考虑用构建器:javaBeans模式可能处于不一致性 ——- Effective java source
下面顺便贴一下Request初始化的源码:
public static class Builder {
private HttpUrl url;
private String method;
private Headers.Builder headers;
private RequestBody body;
private Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
private Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tag = request.tag;
this.headers = request.headers.newBuilder();
}
....
/**
* 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 websocket 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);
}
HttpUrl parsed = HttpUrl.parse(url);
if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}
.....
/**
* Sets the header named {@code name} to {@code value}. If this request already has any headers
* with that name, they are all replaced.
*/
public Builder header(String name, String value) {
headers.set(name, value);
return this;
}
Dispatcher
- 接下来该解析网络请求的部分
首先来介绍一下Dispatcher,OkHttp的调度器,负责OkHttp中同步异步,http 缓存,限制最大host和requst等的调度
首先来看其类:
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
private Runnable idleCallback;
/** Executes calls. Created lazily. */
private ExecutorService executorService;
/** Ready async calls in the order they'll be run. */
缓存的call队列
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
异步的call队列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
同步的call队列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
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;
}
......
ok Dispatcher介绍玩之后,接着看OkHttp源码,request和OkHttpClient初始化已经完毕,接着看:
okHttpClient.newCall(request);
接着看源码:
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
protected RealCall(OkHttpClient client, Request originalRequest) {
this.client = client;
this.originalRequest = originalRequest;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client);
}
其实就是RealCall的初始化,RealCall把初始化的OkHttpClient和ReQuest还有重连的拦截器(一会会提到),之后会使用RealCall来进行异步或者同步调用:
call =okHttpClient.newCall(request);
call.enqueue(new CallBack() {
@Override
protected void onFail() {
}
@Override
protected void onSuccess() {
}
});
这里的call就是realCall,继续栏realCall的equeue:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
接着看AsyncCall:
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl().toString());
this.responseCallback = responseCallback;
}
.....
@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 {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}
....
需要注意的是AsyncCall继承自runnable,而runnable中run方法有调用execute;
继续回溯上一代码段: client.dispatcher().enqueue(new AsyncCall(responseCallback));来看dispatcher的enqueue:
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
通过判断线程池钟request数目,来决定这个request是执行还是先存入缓存队列,核心代码:executorService().execute(call),其实就是new ThreadPoolExecutor(…).execute(call):
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
注意上面代码execute的参数是AsynCall,思路要清晰,继续看addWorker:
private boolean addWorker(Runnable firstTask, boolean core) {
......
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
AsynCall作为参数firstTask继续传递,然后作为一个Thread传入Worker,并初始化w.thread;
w = new Worker(firstTask);
final Thread t = w.thread;
之后t.start就是回调到AsynCall的run,进而调AsynCall的execute;很明了了,网络请求在AsynCall的execute中进行;回头看AsynCall的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 {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}
首先看下finally这是请求完毕之后的善后工作:
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
.....
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();
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.
}
}
其实就是请求完毕之后,利用迭代器遍历readyAsyncCalls,然后加入runningAsyncCalls,进行新一轮的请求,看完finally之后需要回溯上一代码块看AsynCall钟execute:
Response response = getResponseWithInterceptorChain();
这个是返回请求的终极代码;拦截器返回响应response,然后会调成功或失败的callback接口就ok了;
OkHttp的拦截器其实是一个拦截器链,所以在下一篇博文中介绍:
OkHttp源码分析—-拦截器链
感谢阅读~ 期待一起进步