一、同步/异步请求代码简单实现
OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
//同步请求
public void synRequest(){
Request request = new Request.Builder().url("http://www.baidu.com").get().build();
Call call = client.newCall(request);
try {
Response response = call.execute();
Log.e(TAG, "synRequest: "+response.body().string() );
} catch (IOException e) {
e.printStackTrace();
}
}
//异步请求(onFailure和onResponse均在工作线程回调)
public void asyRequest(){
Request request = new Request.Builder().url("http://www.baidu.com").get().build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, "asyRequest: "+response.body().string() );
}
});
}
二、OKhttp请求源码分析
1、创建OKhttpClient对象
OKhttpClient的Builder方法源码分析:
Builder为OKhttpClient中的静态内部类
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;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
dispatcher是OKhttp中比较核心的一个类,是分发器类,可以决定异步请求是缓存还是执行,把同步请求放入请求队列。
2、构建携带请求信息的Request对象
Request的builder方法源码分析:
public Builder() {
this.method = "GET";//定义请求方式为get
this.headers = new Headers.Builder(); //创建Header用于保存请求头部信息
}
build()方法源码,就是把之前配置好的请求方法、头部信息、URL传给Request对象:
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
Request的构造方法源码,里面就是请求的一些信息:
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;
}
3、call的newCall实际调用的RealCall
RealCall的构造方法:
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client; //之前创建的client对象
this.originalRequest = originalRequest; //之前的request请求
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket); //维护了重定向拦截器
}
RealCall 的execute方法实现:
@Override public Response execute() throws IOException {
synchronized (this) {
//同一个http请求只能执行一次,如果没有就把executed设为true,如果执行过则抛出异常
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
//捕捉http请求的异常堆栈信息
captureCallStackTrace();
//监听方法,每当http请求开启execute或enqueue都会开启此监听方法
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);//主动回收同步请求
}
}
client.dispatcher().executed(),dispatcher的同步请求将请求添加到队列之中
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
runningSyncCalls队列在dispatch中定义:
/** 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<>(); //同步执行队列
同步请求中dispatch的finish方法源码:
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
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 = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
runningCallsCount源码:
public synchronized int runningCallsCount() {
//正在执行的异步请求和同步请求之和
return runningAsyncCalls.size() + runningSyncCalls.size();
}
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));
}
AsyncCall源码:
//AsyncCall 继承NamedRunnable
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
......
}
NamedRunnable源码:
//NamedRunnable实际实现了Runnable接口
public abstract class NamedRunnable implements Runnable {
protected final String name;
......
}
继续分析dispatch的enqueue方法:
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
......
synchronized void enqueue(AsyncCall call) {
//判断正在运行的异步请求数是否小于最大请求数,每台主机的运行请求数是否小于每台主机的最大请求数
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
异步请求会先判断运行的异步请求数是否小于64,每台主机的运行请求数是否小于5,才会把请求添加到请求队列中,然后由线程池去执行请求。如果不是就会把该请求加到等待队列中。
线程池对象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;
}
executorService的execute方法的实现在AsyncCall的execute方法中,源码如下:
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
//当重试拦截器被取消,会调用onFailure方法,否则会调用onResponse方法
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);
}
}
异步的dispatch的finished方法:
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();
}
}
总结:
1.创建一个OkHttpClient对象
2.构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象
3.执行call的enqueue方法
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OkHttp拦截器
官网:拦截器是OkHttp中提供一种强大机制,它可以实现网络监听、请求以及相应重写、请求失败重试等功能
RetryAndFollowUpInterceptor
BridgeInterceptor
CacheInterceptor
ConnectInterceptor
CallServerInterceptor
1.创建一系列拦截器,并将其放入一个连接器list中
2.创建一个拦截器链RealInterceptorChain,并执行拦截器链的proceed方法
1.在发起请求前对request进行处理
2.调用下一个拦截器,获取respose
3.对response进行处理,返回上一个拦截器
RetryAndFollowUpInterceptor
1.创建StreamAllocation对象
2.调用RealInterceptorChain.proceed(...)进行网络请求
3.根据异常结果或者响应结果判断是否进行重新请求
4.调用下一个拦截器,对respose进行处理,返回给上一个拦截器
BridgeInterceptor
1.负责将用户构建的一个Request请求转化为能够进行网络访问的请求
2.将这个符合网络请求的Request进行网络请求
3.将网络请求回来的响应Response转化为用户可用的Response