Okhttp学习笔记
学习资料:
同步请求
发起请求后,会进入阻塞状态,直到收到响应
使用步骤
- 创建一个OkHttpClient对象
- 构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象
- 执行call的execute方法
源码浅析
创建okhttpclient
// 建造者模式
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new RetryInterceptor())
.addInterceptor(new LogInterceptor())
.connectTimeout(CONNECT_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS)
.readTimeout(READ_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS)
.writeTimeout(WRITE_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS)
.build();
okhttpclient使用了建造者模式,看一下Builder,只列了一些基本的,后续慢慢学慢慢补上
//构造方法
public Builder() {
dispatcher = new Dispatcher(); // 请求分发 在这里初始化了一个分发器
connectionPool = new ConnectionPool(); // 连接池
...
connectTimeout = 10_000; // 默认10秒
readTimeout = 10_000; // 默认10秒
...
}
// 其中一个方法 添加拦截器
public Builder addInterceptor(Interceptor interceptor) {
if (interceptor == null) throw new IllegalArgumentException("interceptor == null");
interceptors.add(interceptor);
return this;
}
// 最后调用build方法
public OkHttpClient build() {
return new OkHttpClient(this);
}
OkHttpClient类
构造器接收一个Builder参数,如果没有传入,则会新建一个默认的Builder,然后把Builder的参数给到OkHttpClient。
public OkHttpClient() {
this(new Builder());
}
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher; // 重要的一个分发类
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
...
}
构建Request对象
构建
Request request = new Request.Builder()
.url("www.baidu.com") // 传入url地址
.get() // get请求
.headers(mHeadBuilder.build()) // 传入请求头
.build();
Request类同样使用建造者模式,Request.Builder:
public static class Builder {
HttpUrl url; // url 里面有scheme、host、port等数据
String method; // “GET” 或者 “POST”
Headers.Builder headers; // 请求头,这里传入的是他的Builder
RequestBody body;
// 默认参数,可以看到默认为GET请求
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
/** Removes all headers on this builder and adds {@code headers}. */
/** 移除这个构建器所有的请求头,并添加 */
public Builder headers(Headers headers) {
this.headers = headers.newBuilder();
return this;
}
// build方法返回 Request
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
}
Headers类,用于添加请求头等参数
看一下上面用到的newBuilder方法
public Builder newBuilder() {
Builder result = new Builder();
Collections.addAll(result.namesAndValues, namesAndValues);
return result;
}
namesAndValues在Headers.Builder是一个List,在Headers会被转换成一个String[]
public static final class Builder {
final List<String> namesAndValues = new ArrayList<>(20);
}
public final class Headers {
private final String[] namesAndValues;
}
Request类
把传入的Builder中的参数赋值
public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Map<Class<?>, Object> tags;
private volatile CacheControl cacheControl; // Lazily initialized.
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tags = Util.immutableMap(builder.tags);
}
}
构建Call对象
使用前面构建的 client和request,执行client的newCall方法构建Call对象
Call对象代表一个网络请求
Call call = client.newCall(request);
// client 中的newCall方法 RealCall.newRealCall方法具体见下面
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false);
}
Call 是一个接口,真正执行的是他的实现类RealCall
public interface Call extends Cloneable {
/** 返回初始的request对象 */
Request request();
Response execute() throws IOException;
void enqueue(Callback responseCallback);
/*是否已经执行请求*/
boolean isExecuted();
boolean isCanceled();
Call clone();
interface Factory {
Call newCall(Request request);
}
}
RealCall
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client; // 持有
this.originalRequest = originalRequest; // 持有
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket); // 重定向拦截器
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
完成同步请求
执行call.execute();就完成了一次同步请求,并获取response响应对象
try {
Response response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
真正执行的是RealCall.execute()
@Override public Response execute() throws IOException {
// 确保每个请求只请求一次
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace(); // 捕捉异常堆栈信息
eventListener.callStart(this); // 监听事件 监听每次call执行请求(同步或者异步)
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); // 重点 回收
}
}
可以看到真正执行的是调用了是Dispatcher分发器类执行的executed和finish
Dispatcher:
/---------------保存同步请求、移除同步请求-----------------/
synchronized void executed(RealCall call) {
runningSyncCalls.add(call); //添加到队列,保存同步请求
}
/-----------------回收同步请求----------------------------/
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(); // 获取正在执行的请求数
idleCallback = this.idleCallback;
}
// 执行数为0时,且idleCallback 不为空,执行idleCallback.run();
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
异步请求
- 创建一个okhttpClient对象
- 构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象
- 执行call的enqueue方法
前两步都是一样的,只有第三步是不一样的,主要看一下第三步
(强调:回调的两个方法都处于工作线程)
完成异步请求
// enqueue方法: 需要传入一个Callback 对象,用于接收返回值
void enqueue(Callback responseCallback);
// 前两步获取到的call对象,执行enqueue方法
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
源码浅析
上面提到真正执行的是 Call接口的实现类RealCall:
@Override public void enqueue(Callback responseCallback) {
// Call只能执行一次
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace(); // 捕捉异常信息
eventListener.callStart(this);
// 关键 封装了一个AsyncCall对象
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
AsyncCall对象:继承于NameRunable (实现了 Runnable接口)
Dispatcher()的enqueue方法
synchronized void enqueue(AsyncCall call) {
// maxRequests 和 maxRequestsPerHost 是定义的常量,规定了最大的请求数、最大主机请求数
// 判断是否小于最大数,若是,则添加进请求队列中,并调用线程池执行(AsyncCall 实现了Runnable)
// 如果超过了最大值,则添加到缓存等待的请求队列
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call); // 调用线程词执行
} else {
readyAsyncCalls.add(call);
}
}
小结:
- 先判断是否已经执行
- 将Call封装成一个AsyncCall对象
- 调用client.dispatcher().enqueque(AsyncCall asyncCall)【判断是否超过最大值,添加、执行请求】
那么接下来的重点就是
executorService().execute(AsyncCall call);
executorService().execute() 方法
源码:
public synchronized ExecutorService executorService() {
// 保持单例 核心线程为 0
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
创建后执行:线程词会调用子线程的run方法,AsyncCall 继承于 NameRunnnable,并且重写了execute方法,而在NameRunnable里,实现了run方法但是只是把execute这个抽象方法包装起来,所以具体实现在AsyncCall的execute方法:
final class AsyncCall extends NamedRunnable {
...
@Override protected void execute() {
boolean signalledCallback = false;
try {
// 获取拦截器链 获取response
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) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
// 捕获到异常 回调到onFailure方法
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
// 调用finished方法
client.dispatcher().finished(this);
}
}
...
}
总结:
- 先判断是否已经执行
- 将Call封装成一个AsyncCall对象
- 调用client.dispatcher().enqueque(AsyncCall asyncCall)【判断是否超过最大值,添加、执行请求】
而后:
- dispatcher().enqueque 方法进行了判断,如果没有超过请求的最大数值和主机数值,则会调用线程池执行AsyncCall 中的execute方法
- AsyncCall 中的execute方法 通过getResponseWithInterceptorChain()方法获取到了response,之后进行一系列的判断,回调到onResponse或者onFailure方法
关于Dispatcher类详解: