OkHttpClient okHttpClient = new OkHttpClient.Builder().build();//创建单例
Request request = new Request.Builder()//创建请求
.url("http://www.baidu.com")
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG,"失败");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG,"成功");
}
});
与同步请求一样前三步
第一步创建了OKHttpClient
第二步创建Request
第三步需要创建一个Call对象
其实前三步骤并没有进行真正的发起网络请求,只是帮我们做了网络请求前期的操作,其实真正的网络请求是在第四步当中
第四步调用enqueue
public void enqueue(Callback responseCallback) {
synchronized(this) { //锁住了当前的对象,this指的是RealCall这个对象
if (this.executed) {//用于表示这个RealCall的这个实例是否执行过,如果执行过了就会抛出异常,表明enqueue只能执行一次
throw new IllegalStateException("Already Executed");
}
this.executed = true;//如果没有执行过,就会设置true
}
this.client.dispatcher().enqueue(new RealCall.AsyncCall(responseCallback));//①AsyncCall②enqueue
}
①的执行方法
final class AsyncCall extends NamedRunnable { //继承了Runnable
private final Callback responseCallback;
private AsyncCall(Callback responseCallback) {
super("OkHttp %s", new Object[]{RealCall.this.redactedUrl().toString()});
this.responseCallback = responseCallback;
}
}
②的执行方法
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque();//运行在dispatcher中 判断并发请求的数量
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque();//表示缓存等待的请求队列
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
synchronized void enqueue(AsyncCall call) {
if (this.runningAsyncCalls.size() < this.maxRequests && this.runningCallsForHost(call) < this.maxRequestsPerHost) {
//判断当前异步请求的数量是否小于最大请求数,以及正在运行的主机的请求是否小于设定的主机请求的最大值
this.runningAsyncCalls.add(call);//帮当前请求的AsyncCall加到异步队列中
this.executorService().execute(call);//通过这个线程池去执行这个异步请求
} else {
this.readyAsyncCalls.add(call);//如果超出了设定的值,就会放到等待队列当中
}
}
这个方法的意思是:当你要发起一个异步的网络请求的时候,它首先会判断当前正在请求的Runnale的个数是否小于它的最大值否则就会加入等待的队列当中
总结:首先通过执行call.enqueue()这个方法,第一步会判断是否只执行了一次如果不是的话就会抛出异常,第二步通过传递进来的一个CallBack对象,把它封装成了一个AsyncCall对象,这个对象其实就是Runnable对象第三步构建AsyncCall对象之后,通过dispather调用enqueue方法进行异步的网络请求,同时当前异步请求的数量是否小于64,以及正在运行的主机的请求是否小于设定的5个请求,就会把当前的AsyncCall请求放到请求异步队列当中,如果超出设定的值就会放到等待就绪的异步队列当中
接下来分析一下OKHttp的线程池
public synchronized ExecutorService executorService() {// synchronized锁住了该方法
if (this.executorService == null) {
this.executorService = new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
return this.executorService;
}
可以从上面方法中看出,当executorService为空的时候才可以创建,不为空的时候就直接return,很明显当前线程池的方法是一个单例。
由于它是个线程池,我们就会调用每个子线程的Run方法,通过执行this.executorService().execute(call);就会调用AynscCall的run方法,接下来看一下AsyncCall是如何做的实现
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private AsyncCall(Callback responseCallback) {
super("OkHttp %s", new Object[]{RealCall.this.redactedUrl().toString()});
this.responseCallback = responseCallback;
}
String host() {
return RealCall.this.originalRequest.url().host();
}
Request request() {
return RealCall.this.originalRequest;
}
RealCall get() {
return RealCall.this;
}
protected void execute() {
boolean signalledCallback = false;
try {
Response response = RealCall.this.getResponseWithInterceptorChain();
if (RealCall.this.retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
this.responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
this.responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException var6) {
if (signalledCallback) {
Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var6);
} else {
this.responseCallback.onFailure(RealCall.this, var6);
}
} finally {
RealCall.this.client.dispatcher().finished(this);
}
}
}
但是这个里面是没有Run方法的,去NamedRunnable看一下
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(this.name);
try {
this.execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute(); //抽象的方法
}
原来转了一圈又回去了,其实execute() 就是在Run方法里面,execute方法才是具体的实现
接下来看一下execute方法
protected void execute() {
boolean signalledCallback = false;
try {
Response response = RealCall.this.getResponseWithInterceptorChain();//在同步方法中也执行了这个方法,这个拦截链后续会详细的详解,这个其实就是构建拦截器的链,而每一个拦截器链中的拦截器是不同作用的通过这个方法会返回Response对象
if (RealCall.this.retryAndFollowUpInterceptor.isCanceled()) {//来判断这个拦截器链当中的一个拦截器叫做重定向和重试拦截器,这个拦截器是否取消了
signalledCallback = true;
this.responseCallback.onFailure(RealCall.this, new IOException("Canceled"));//如果取消了就会调用onFailure方法
} else {
signalledCallback = true;
this.responseCallback.onResponse(RealCall.this, response);//如果没有被取消就辉调用onResponse这个回调方法,这里是做网络请求操作的
}
} catch (IOException var6) {
if (signalledCallback) {
Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var6);
} else {
this.responseCallback.onFailure(RealCall.this, var6);
}
} finally {
RealCall.this.client.dispatcher().finished(this);//③主动回收异步请求
}
}
由此方法可知,不管是onFailure还是onResponse都是在子线程里面做的,所以如果要做一些UI显示一定要在主线程里来做
③的执行方法
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) {
this.promoteCalls();//调整我们整个异步请求任务队列
}
runningCallsCount = this.runningCallsCount();//重新计算正在执行的线程数量然后赋值
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {//如果当前线程数量为0的话而且当前的callback不为空的情况下执行run
idleCallback.run();
}
}
总结:第一步创建一个OKHttpClient对象,这个是OKHttp请求的客户端类,第二步构建一个Request对象,通过它的bulider模式创建它的url参数头部信息等等,通过OKHttpClient和Request对象,构建出实际的OKhttp请求Call对象,最后执行call的enqueue方法,把整个OKHttp请求放到调度器当中,由于是异步的给他注入CallBack对象以便用来网络请求的分发过程。下一篇会详细的介绍dispatcher分发器