1.okhttp 特点:
1.支持HTTPS/HTTP2/WebSocket(在OkHttp3.7中已经剥离对Spdy的支持,转而大力支持HTTP2)
2.内部维护任务队列线程池,友好支持并发访问
3.内部维护连接池,支持多路复用,减少连接创建开销
4.socket创建支持最佳路由
5.提供拦截器链(InterceptorChain),实现request与response的分层处理(如透明GZIP压缩,logging等)
2.okhttp的同步和异步使用
同步
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder().build();
try {
okHttpClient.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
1.new 一个okhttpclient对象,在其构造方法会初始化一系列数据(缓存,调度者,超时时间等)
2.通过Builder()方法初始化请求方法和请求头,然后通过build()方法做校验,new 出request对象
3.通过调用okhttpclient的newCall()方法将request请求传入然后执行execute()方法
newCall()内部会创建一个realCall的对象,而realCall是一个抽象类Call的实现类。
实现抽象类Call
执行型reallCall的execute()方法
首先先判断该任务是否执行,如果已执行则抛出“Already Executed”异常
如果任务没有执行,则由调度者执行这个任务,将任务添加到同步执行的队列里,执行任务。
通过调用getResponseWithInterceptorChain()这个方法得到Response相应 。下面与异步任务一起分析,此处就不再过多讲述。
当任务执行完毕后,调度者会执行finished(this)方法,将任务从队列里移除。
异步调用
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder().build();
try {
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
} catch (Exception e) {
e.printStackTrace();
}
因为异步任务与同步任务的不同之处在于任务执行的execute()方法处,所以我们此处不讲相同的地方,着重分析execute(new Callback())方法,按住control键进入execute(new Callback())源码
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
//调度器执行enqueue()方法,传入new AsyncCall()对象
synchronized void enqueue(AsyncCall call) {
//判断正在运行的异步任务数量小于最大请求数(默认为64),并且判断同一host的请求数小于同一host的最大请求数(默认为5)
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
//如果满足条件将任务加入到正在执行的任务队列
runningAsyncCalls.add(call);
//线程池执行任务
executorService().execute(call);
} else {
//否则加入到等待执行的任务队列
readyAsyncCalls.add(call);
}
}
//线程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
//创建一个核心线程数为0,非核心现场数最大为整形最大值(2的31次方-1)的线程池,空闲时间为60s
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
//AsyncCall对象继承抽象类NamedRunnable对象,NamedRunnable对象实现了Runnable接口并实现了run()方法
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 {
//AsyncCall 中将会重写该方法
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
//AsyncCall 类中重写NamedRunnable的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;
//返回response
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);
}
}
//任务执行完后调度者调用的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();
}
}
//从等待队列中取任务,加入到正在执行的队列,然后线程池执行任务。
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.
}
public synchronized int runningCallsCount() {
return runningAsyncCalls.size() + runningSyncCalls.size();
}
以上带大家简单分析了一下okhttp的同步调用和异步调用的基本流程相信大家对okhttp的工作原理已经有了一个简单的了解。下一节我将带大家一起分析一下okhttp的拦截器。