一,概述
1,OkHttpClient对象的创建。
2,Request 对象的创建。
3,Call对象的创建
4,Call的execute方法实现同步请求。
5,Call的enqueue方法实现异步请求,异步请求是怎么开启的子线程。
二,OkHttpClient对象的创建
OKHttpClient对象的创建方式有两种。
第一种是使用构造方法创建对象:
OkHttpClient client = new OkHttpClient();//使用构造方法直接创建OkHttpClient对象。
第二种是使用Builder模式创建对象:
OkHttpClient.Builder builder = new OkHttpClient.Builder();//先创建构建者对象
builder.connectTimeout(3*1000, TimeUnit.MILLISECONDS);//设置超时时间
OkHttpClient client = builder.build();//使用构建者创建OkHttpClient对象。
这两种创建模式本质上是一样的。用的是建造者设计模式(builder)
构造方式的源码(本质上还是用的builder,初始化参数是默认的)
public OkHttpClient() { this(new Builder()); }
Builder是OkHttpClient的内部类,创建Builder对象使用的是builder的无参构造方法。主要功能就是进行一些字段的初始化。
三,Request 对象的创建
Request 也是Builder设计模式,
//get请求
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Builder类是Request 的内部类,与OkHttpClient的内部类Builder不是同一个。
下面看Request 的内部类Builder的无参构造原码:Builder对象时默认把请求方式设置为GET
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
request 可是设置请求头header。有三个方式
Request request = new Request.Builder()
.url(url)
.header("User-Agent",getUserAgent())
.addHeader("key","value)
.addHeaders(new Headers.Builder().build())//传递一个headers对象,
.build();
private static String getUserAgent( String userAgent) {
StringBuffer sb = new StringBuffer();
for (int i = 0, length = userAgent.length(); i < length; i++) {
char c = userAgent.charAt(i);
if (c <= '\u001f' || c >= '\u007f') {
sb.append(String.format("\\u%04x", (int) c));
} else {
sb.append(c);
}
}
return sb.toString();
}
四,Call对象的创建
创建call对象:
client.newCall(request)
OKHttpClient类的newCall方法的原码:
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
这个方法的作用是创建RealCall对象,并把client对象和request对象都传递过去了。
1,RealCall是Call接口的实现类,Call调用的方法的实现都在RealCall类中,这个类是关键类。
2,将client对象和request对象传递给了RealCall对象,这样等于RealCall对象拥有了client的属性值和request对象的属性值。即我们在前面对client设置的属性值和对request设置的属性值都传递到了这个对象中。
五,RealCall的execute方法实现同步请求。
RealCall类的execute方法的源码:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
核心代码是:Response result = getResponseWithInterceptorChain()。这个方法中返回的result 即是我们需要的响应数据。
六,RealCall的enqueue方法实现异步请求
RealCall类的enqueue方法的源码:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
分析:
1,这里的client就是前面创建的OKHttpClient对象。
2,client.dispatcher()方法返回Dispatcher对象,这个类成为调度着,这个对象的创建在OKHttpClient的内部类Builder的构造方法中。
3,重点有两个,一个是Dispatcher的enqueue方法,一个是AsyncCall对象。
下面先看Dispatcher的enqueue方法的源码:
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
这是一个同步方法,核心代码是:executorService().execute(call);
下面首先看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;
}
这个方法创建了一个线程池对象,这个线程池的特点是:
1,核心线程数为0。
2,最大线程数是Integer的最大值,这里可以理解为无限多。
3,非核心线程存活时间为60秒。
分析:这个线程池没有核心线程,非核心线程的存活时间只有60秒,所以这个线程池的优点不是特别突出。
下面继续看:executorService().execute(call);
executorService()返回一个线程池对象,我们知道execute方法接收Runnable对象,Runnable的run方法执行在子线程。下面开下这个call对象。
这个call对象来源于:client.dispatcher().enqueue(new AsyncCall(responseCallback));
下面看AsyncCall类。
AsyncCall类是RealCall的内部类,AsyncCall继承NamedRunnable类,NamedRunnable又继承Runnable类。在NamedRunnable类中声明了一个抽象方法execute(),且在run方法中调用了。我们由代码executorService().execute(call)知道此时会调用run方法,从而会调用execute方法。
下面看AsyncCall的execute方法的源码(注意:这个方法执行在子线程):
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
responseCallback.onResponse(RealCall.this, response);
}
}
}
在这个方法中我们看到了熟悉的代码:
Response response = getResponseWithInterceptorChain();
这行代码在同步请求中已经看到过,它是网络请求的核心。到此同步请求和异步请求都殊途同归到了getResponseWithInterceptorChain方法上。不同的是:异步请求是在子线程中调用的getResponseWithInterceptorChain方法。
此外在这儿我们看到了CallBack的onFailure方法和onResponse方法被调用。由于execute方法执行在子线程,所以onFailure方法和onResponse方法都是执行在子线程。
注意事项:
1,在RealCAll的enqueue方法中通过线程池的方式开启了子线程。
2,CallBack的onFailure方法和onResponse方法都执行在子线程中,所以在更新UI时还需要跳转到UI线程。