源码在:https://github.com/square/okhttp
包实在是太多了,OKhttp核心在这块https://github.com/square/okhttp/tree/master/okhttp
直接导入Android Studio中即可。
基本使用:
//1、创建OkHttpClient
OkHttpClient mOkHttpClient = new OkHttpClient();
//2、创建Request
final Request request = new Request.Builder()
.url("https://www.jianshu.com/u/b4e69e85aef6")
.addHeader("user_agent","22222")
.build();
//3、创建Call
Call call = mOkHttpClient.newCall(request);
//4、执行call.enqueue
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response != null )
Log.i(TAG, "返回服务端数据:"+ String.valueOf(response.body().string()));
}
});
源码解析:
1、创建OkHttpClient
//OkHttpClient.java
public OkHttpClient() {
this(new Builder());
}
OkHttpClient(Builder builder) {
//调度器
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
//默认支持的Http协议版本 -- Protocol.HTTP_2, Protocol.HTTP_1_1;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = Util.platformTrustManager();
this.sslSocketFactory = newSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
if (sslSocketFactory != null) {
Platform.get().configureSslSocketFactory(sslSocketFactory);
}
this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
this.pingInterval = builder.pingInterval;
if (interceptors.contains(null)) {
throw new IllegalStateException("Null interceptor: " + interceptors);
}
if (networkInterceptors.contains(null)) {
throw new IllegalStateException("Null network interceptor: " + networkInterceptors);
}
}
通过建造者模式为我们设置默认的OKhttpClient
2、创建Request
//Request.java
Request(Builder builder) {
//请求的url
this.url = builder.url;
//请求的方式
this.method = builder.method;
//请求头
this.headers = builder.headers.build();
//请求体
this.body = builder.body;
this.tags = Util.immutableMap(builder.tags);
}
//具体的设置我就不贴了,可以看出通过建造者模式创建Request
public Builder newBuilder() {
return new Builder(this);
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
通过建造者模式创建Request
3、创建Call
Call call = mOkHttpClient.newCall(request);
源码:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
可以看出,调用了RealCall.newRealCall方法,继续往下看
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对象
4、执行RealCall.enqueue方法,异步请求
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
//为保证线程安全,若已经执行,抛出IllegalStateException
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//重点在这里
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
可以看出最终的请求是dispatcher来完成的
看一下同步请求代码:
@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);
}
}
在这里可以看出
异步请求调用了dispatcher().enqueue
同步请求调用了dispatcher().executed
接下来分析dispatcher
5、Dispatcher
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 readyAsyncCalls = new ArrayDeque<>();
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
//正在运行的异步请求队列
private final Deque runningAsyncCalls = new ArrayDeque<>();
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
//正在运行的同步请求队列
private final Deque runningSyncCalls = new ArrayDeque<>();
接下来看看Dispatche的构造方法
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
public synchronized ExecutorService executorService() {
if (executorService == null) {
//如果用户没有设置自己的线程池,自OKhttp初始化默认的线程池
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
Dispatcher有两个构造方法,可以使用自己的线程池。如果没有设置自己的线程池,则会设置默认的线程池。这个线程池类类似于CachedThreadPool,比较适合执行大量的耗时比较少的任务。
接下来看看Dispatcher的同步执行方法
/** Used by {@code Call#execute} to signal it is in-flight. */
synchronized void executed(RealCall call) {
//将请求添加到同步运行队列
runningSyncCalls.add(call);
}
Dispatcher的异步执行方法
synchronized void enqueue(AsyncCall call) {
/*当正在运行的异步请求队列中的数量小于64并且正在运行的请求主机数小于5时
把请求添加到runningAsyncCalls
否则,将请求添加到readyAsyncCalls
*/
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
接下来调用executorService().execute(call);,实际调用的是AsyncCall的execute方法,接下来分析
6、AsyncCal的execute方法
AsyncCall是RealCall的内部类,其内部也实现了execute方法,如下:
@Override protected void execute() {
boolean signalledCallback = false;
try {
//在这块实现了网络请求,并返回Response
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 response = getResponseWithInterceptorChain();
中执行
下面分析getResponseWithInterceptorChain()
7、RealCall.getResponseWithInterceptorChain()
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
//添加各种Interceptor
List 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);
}
可以看出创建了RealInterceptorChain它是一个拦截器链,这个类也是RealCall的内部类,接下来执行它的proceed方法
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);
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;
}
拦截器的作用
来自官网的英文原文:
Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.
意思大概是,拦截器是一个强有力的机制,,它可以实现网络监听、请求以及响应重写、请求失败重试等功能。
这里不做过多分析,具体详情可以看看这篇文章
https://blog.csdn.net/lepaitianshi/article/details/72457928
具体的网络请求已经在拦截器中实现
* CacheInterceptor实现缓存管理*
@Override public Response intercept(Chain chain) throws IOException {
Response cacheCandidate = cache != null
? cache.get(chain.request())
: null;
long now = System.currentTimeMillis();
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
//网络请求
Request networkRequest = strategy.networkRequest;
//缓存响应
Response cacheResponse = strategy.cacheResponse;
if (cache != null) {
//记录当前请求是网络发起还是缓存发起
cache.trackResponse(strategy);
}
if (cacheCandidate != null && cacheResponse == null) {
closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
}
// If we're forbidden from using the network and the cache is insufficient, fail.
//不进行网络请求,并且缓存不存在,则返回504错误
if (networkRequest == null && cacheResponse == null) {
return new Response.Builder()
.request(chain.request())
.protocol(Protocol.HTTP_1_1)
.code(504)
.message("Unsatisfiable Request (only-if-cached)")
.body(Util.EMPTY_RESPONSE)
.sentRequestAtMillis(-1L)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
}
// If we don't need the network, we're done.
//如果不进行网络请求,而且缓存可用,则直接返回缓存
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build();
}
//请求网络
Response networkResponse = null;
try {
networkResponse = chain.proceed(networkRequest);
} finally {
// If we're crashing on I/O or otherwise, don't leak the cache body.
if (networkResponse == null && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}
// If we have a cache response too, then we're doing a conditional get.
//如果存在缓存,并且服务器没有修改数据(networkResponse.code() == HTTP_NOT_MODIFIED),则返回缓存
if (cacheResponse != null) {
if (networkResponse.code() == HTTP_NOT_MODIFIED) {
Response response = cacheResponse.newBuilder()
.headers(combine(cacheResponse.headers(), networkResponse.headers()))
.sentRequestAtMillis(networkResponse.sentRequestAtMillis())
.receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
networkResponse.body().close();
// Update the cache after combining headers but before stripping the
// Content-Encoding header (as performed by initContentStream()).
cache.trackConditionalCacheHit();
cache.update(cacheResponse, response);
return response;
} else {
closeQuietly(cacheResponse.body());
}
}
//f否则进行网络请求
Response response = networkResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
if (cache != null) {
if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
// Offer this request to the cache.
CacheRequest cacheRequest = cache.put(response);
return cacheWritingResponse(cacheRequest, response);
}
if (HttpMethod.invalidatesCache(networkRequest.method())) {
try {
cache.remove(networkRequest);
} catch (IOException ignored) {
// The cache cannot be written.
}
}
}
return response;
}
如果缓存存在而且没有过期(服务器返回数据为304),则返回响应,否则请求网络
这里的缓存均基于Map,key是请求中url的md5,value是文件中查询到的缓存,页面置换基于LRU算法。
至此源码就分析到这,主要是拦截器链起作用,具体的话,可以看看这篇文章
https://blog.csdn.net/lepaitianshi/article/details/72457928