同步请求示例
//实例化请求客户端
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout( 5, TimeUnit.SECONDS )
.build();
//实例化请求对象
Request request = new Request.Builder()
.url( "http://www.baidu.com" )
.get()
.build();
//和服务端建立连接的call
Call call = okHttpClient.newCall( request );
try {
//同步请求,返回体,同步会阻塞线程直到响应
Response response = call.execute();
String s = response.body().toString();
Log.i( TAG, "synRequest:>>>"+s );
} catch (IOException e) {
e.printStackTrace();
}
异步请求示例
//实例化请求客户端
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout( 5, TimeUnit.SECONDS )
.cache( new Cache( new File( "cache" ),20*1024*1024 ) )//缓存大小
.build();
//实例化请求对象
Request request = new Request.Builder()
.url( "http://www.baidu.com" )
.get()
.build();
//和服务端建立连接的call
Call call = okHttpClient.newCall( request );
//异步请求
call.enqueue( new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i( TAG, "onFailure:>>>" );
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i( TAG, "onResponse:>>>"+response.body().string() );
}
} );
同步和异步调用只有在最后发起请求时有差别,前面构造OkHttpClient ,Request ,Call 流程相同。我们先看OkHttpClient.Builder()的构造过程。
public static final class Builder {
Dispatcher dispatcher;//是同步还是异步的分发
......
ConnectionPool connectionPool;//连接池
......
int readTimeout;//读取超时
,,,,,,
public Builder() {
dispatcher = new Dispatcher();
......
connectionPool = new ConnectionPool();
......
}
//保存到成员变量
public Builder readTimeout(long timeout, TimeUnit unit) {
readTimeout = checkDuration("timeout", timeout, unit);
return this;
}
// 构造OkHttpClient
public OkHttpClient build() {
return new OkHttpClient(this);
}
Builder 模式将我们设置的参数全部保留到成员变量,再build时构造OkHttpClient,并把自己(Builder )传给OkHttpClient。因为一个客户端可以同时发起同步和异步请求,也可以同时发送多个请求,因此Dispatcher和ConnectionPool在客户端就要构造出来。
public static class Builder {
@Nullable HttpUrl url;
String method;
Headers.Builder headers;
@Nullable RequestBody body;
Map, Object> tags = Collections.emptyMap();
public Builder() {
this.method = "GET";//默认get请求
this.headers = new Headers.Builder();
}
Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tags = request.tags.isEmpty()
? Collections., Object>emptyMap()
: new LinkedHashMap<>(request.tags);
this.headers = request.headers.newBuilder();
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
Request包含了请求的报文信息,即请求地址、请求方式、请求头、请求体,它的构建方式和OkHttpClient一样。Call 的构造方式和前面两者不同,它通过RealCall的newRealCall静态方法来构造。
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
.....
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
final class RealCall implements Call {
final OkHttpClient client;
//构造重定向拦截器
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
final AsyncTimeout timeout;
private @Nullable EventListener eventListener;
final Request originalRequest;
final boolean forWebSocket;
private boolean executed;
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
//构造重定向拦截器
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
this.timeout = new AsyncTimeout() {
@Override protected void timedOut() {
cancel();
}
};
this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// 在静态方法里创建
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
源码跟踪看到,Call 的实现只有一个RealCall子类 ,所有参数准备就绪,执行call.execute()同步请求,即调用RealCall 的execute方法
@Override public Response execute() throws IOException {
synchronized (this) {
//同一个Call 请求只能执行一次,执行过将抛异常,这意味着如果要执行多个要重新调用newCall
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
timeout.enter();
eventListener.callStart(this);
try {
//从OkHttpClient获取创建好的Dispatcher,将RealCall加入到成员变量runningSyncCalls 同步队列中
client.dispatcher().executed(this);
//获取请求数据
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
//将数据返回
return result;
} catch (IOException e) {
e = timeoutExit(e);
eventListener.callFailed(this, e);
throw e;
} finally {
//移除掉队列里的某些请求
client.dispatcher().finished(this);
}
}
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
private @Nullable Runnable idleCallback;
private @Nullable ExecutorService executorService;
//异步就绪队列
private final Deque readyAsyncCalls = new ArrayDeque<>();
//异步的执行队列
private final Deque runningAsyncCalls = new ArrayDeque<>();
//同步队列
private final Deque runningSyncCalls = new ArrayDeque<>();
//加入到同步队列中
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
//请求流程完成,异步请求的回收重置
void finished(AsyncCall call) {
finished(runningAsyncCalls, call);
}
//请求流程完成,同步请求的回收重置
void finished(RealCall call) {
finished(runningSyncCalls, call);
}
private void finished(Deque calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
//执行run方法
idleCallback.run();
}
}
可以看到,同步请求的主要逻辑就是把RealCall加入到Dispatcher 维护的runningSyncCalls 队列中。
异步请求和同步请求前几步的创建没有差别,是在realCall执行请求时才区别开来,下面分析异步请求的调用流程。
final class RealCall implements Call {
//执行请求并传入回调
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
//每个call只能执行一次
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//将传递进来的回调封装成AsyncCall
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
每个请求只能执行一次,executed用来判断是否已执行过,并且executed和连接池的实现原理相关,下面分析。最后一步看到,再获取分发器执行enqueue时,将我们出入的回调封装成了AsyncCall对象,它是RealCall的内部类,本质是一个Runnable。
final class RealCall implements Call {
//继承了NamedRunnable
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
获取Dispatcher ,调用enqueue,将AsyncCall 传入
public final class Dispatcher {
//异步请求
void enqueue(AsyncCall call) {
//加到就绪队列中
synchronized (this) {
readyAsyncCalls.add(call);
}
//从就绪队列取出
promoteAndExecute();
}
//从就绪队列取出AsyncCall ,满足请求条件,则加入请求列表,再遍历列表交给线程池执行
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
//遍历就绪队列
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
//执行的请求最多64个
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
//host小于5
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
//取出
i.remove();
//添加到列表中
executableCalls.add(asyncCall);
//添加到执行队列中
runningAsyncCalls.add(asyncCall);
}
//当前有执行的请求
isRunning = runningCallsCount() > 0;
}
//从执行列表取出加入到线程池中执行
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
//获取线程池,调用executeOn
asyncCall.executeOn(executorService());
}
return isRunning;
}
//创建线程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
//虽然最大线程数量用了Integer.MAX_VALUE,但上面分析知道实际不会超过64个
//通过execute提交的AsyncCall会保存到SynchronousQueue这个队列中
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
//当前请求数=同步执行数+异步执行数
public synchronized int runningCallsCount() {
return runningAsyncCalls.size() + runningSyncCalls.size();
}
public final class Util {
//创建新线程的工厂
public static ThreadFactory threadFactory(final String name, final boolean daemon) {
return new ThreadFactory() {
@Override public Thread newThread(Runnable runnable) {
Thread result = new Thread(runnable, name);
result.setDaemon(daemon);
return result;
}
};
}
}
Dispatcher 执行异步请求时,会先将Runnable(即AsyncCall )加入就绪队列中,然后遍历就绪队列,如果满足当前请求数小于等于64,host小于5个,则把当前Runnable移除就绪队列,加入到执行列表中,以等待执行,否则不加入,留在队列中。被添加到执行列表的Runnable将遍历取出,交由线程池执行。
//NamedRunnable 继承了Runnable
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
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
final class RealCall implements Call {
//重定向拦截器
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
//构造重定向拦截器
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
this.timeout = new AsyncTimeout() {
@Override protected void timedOut() {
cancel();
}
};
this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
}
//继承了NamedRunnable
final class AsyncCall extends NamedRunnable {
//保存回调
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
//线程池执行请求
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
//执行run方法
executorService.execute(this);
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
eventListener.callFailed(RealCall.this, ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
//由run方法执行execute
@Override
protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
//获取返回数据,这里是拦截器链,下面分析
Response response = getResponseWithInterceptorChain();
//重定向拦截器是否取消了
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
//失败回调onFailure
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
//没有取消
signalledCallback = true;
//成功回调onResponse
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
e = timeoutExit(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);
}
}
}
由以上分析看到,遍历执行列表后,取出AsyncCall ,调用executeOn,将通过线程池的execute,来执行AsyncCall 的父类的run方法,run方法设置了线程名后,又调用了子类的execute方法,做实际的请求操作,如果重定向拦截器被取消了,则回调我们常见的onFailure方法,没有被取消,则成功回调onResponse方法。
上面分析了同步和异步请求的执行和数据回调的流程,但实际的请求流程还没有分析到。由源码看到,无论同步还是异步,都是通getResponseWithInterceptorChain()来获取请求数据的,其内部是通过实现一条拦截器链,来获取到网络数据的,下篇将分析拦截链调用和最终请求网络数据的流程。