目录
1.OkHttp关键类和类的作用
1.1.OkHttpClient(请求客户端)
1.2.Request
1.3.RealCall
1.4执行请求相关类
1.5.Dispatcher
1.7.BridgeInterceptor
1.8.CacheInterceptor
1.9.ConnectInterceptor
1.10.CallServerInterceptor
2.拦截的调用顺序
1.OkHttp关键类和类的作用
1.1.OkHttpClient(请求客户端)
OkHttpClient是用于生产Call {@linkplain Call calls}的工厂,可以发送请求和读取请求返回的响应信息;
a.OkHttpClients应该被公用的
当我们创建一个{@code OkHttpClient}实例时并且复用它为了所有的HTTP请求调用时将是更高效的。这是因为彼此客户端都拥有自己的连接池和线程池。复用连接和线程将减少延迟并节省内存。相反,为每一个请求都创建客户端将是浪费资源。使用{@code new OkHttpClient()}创建一个有默认配置公用的实例,代码如下;
{@code
// The singleton HTTP client.
public final OkHttpClient client = new OkHttpClient();
}
或者使用 {@code new OkHttpClient.Builder()}去创建一个有定制配置的公用的实例,代码如下;
{@code
// The singleton HTTP client.
public final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor())
.cache(new Cache(cacheDir, cacheSize))
.build();
}
b.使用newBuilder()定制你的客户端
你能使用{@link #newBuilder()}定制一个共享的OkHttpClient的实例。这个将创建一个共享相同连接池,线程池和配置的客户端。使用builder方法去配置为了特殊用途的派生客户端。这个展示一个500毫秒超时的调用例子:
{@code
OkHttpClient eagerClient = client.newBuilder()//判断出来的客户端-共享连接池,线程池等
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
Response response = eagerClient.newCall(request).execute();
}
c.关闭连接或者线程池不是必须的
如果它们保持空闲的,线程和连接将被自动释放。但是,如果您正在编写一个需要积极释放未使用的资源的应用程序,您可以这样做。
关闭dispatcher的线程池服务使用{@link ExecutorService#shutdown shutdown()}。这也会导致将来客户被拒绝的调用。
{@code
client.dispatcher().executorService().shutdown();
}
d.使用{@link ConnectionPool#evictAll() evictAll()}清理连接池。注意,那个连接池的后台线程不能立即退出。
{@code
client.connectionPool().evictAll();
}
e.如果你的客户端有一个缓存,调用 {@link Cache#close close()}。注意去创建一个被关闭的缓存的调用将是错误的,并且这样将引起崩溃。
{@code
client.cache().close();
}
f.OkHttp为了HTTP/2连接也使用后台线程。如果它们空闲,这些连接将自动退出
1.2.Request
包装的一个HTTP请求,如果body是null或者它自己不可变,类的实例也是不可变的;
//包含请求的如下信息
private final HttpUrl url;//请求的url
private final String method;//请求的方法
private final Headers headers;//请求头
private final RequestBody body;//请求的body
private final Object tag;//请求的标记
1.3.RealCall
RealCall是一个封装已经准备去执行的请求的调用。这个调用可以被取消。作为这个对象表示单个请求/响应对(流),不能执行两次。
1.4执行请求相关类
调用RealCall的execute()执行请求时,查看下面RealCall类中请求的方法如下:
@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);
}
}
我们会看到具体执行网络请求关键步骤类的部分,主要有Dispatcher类和RealCall类下getResponseWithInterceptorChain()方法下关键的拦截器类
private Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!retryAndFollowUpInterceptor.isForWebSocket()) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(
retryAndFollowUpInterceptor.isForWebSocket()));
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
RetryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor,CallServerInterceptor。
1.5.Dispatcher
每个Dispatcher使用一个{@ Link ExecutorService }在内部运行调用。如果你提供你的自己的executor,它应该能够运行 {@linkplain #getMaxRequests 配置的最大}数量的并发调用。
1.6.RetryAndFollowUpInterceptor
这个拦截器可以从请求失败和重定向中按需要恢复。 它可能抛出异常 {@link IOException} 如何调用被取消。
1.7.BridgeInterceptor
从应用程序代码到网络代码的桥梁。首先,它从用户请求建立网络请求,然后继续调用网络请求。最后,根据网络响应建立用户响应。
1.8.CacheInterceptor
服务缓存中的请求并向缓存写入响应。
1.9.ConnectInterceptor
打开到目标服务器的连接,并执行下一个拦截器。
1.10.CallServerInterceptor
这是最后一个拦截器,它将调用一个到服务器的网络请求。
2.拦截的调用顺序
