查看:okhttp源码解析_json_it的博客-CSDN博客_okhttp源码
查看:面试准备之okhttp的使用及源码分析(一)_ali18510953445的博客-CSDN博客
查看:Android面试题-OkHttp3源码分析_所有技术文章里面全部配置了配套视频-CSDN博客_android okhttp面试题
OkHttp3基本使用_李林杰的博客-CSDN博客_okhttp3
OkHttp3源码分析_李林杰的博客-CSDN博客_okhttp3源码解析
OkHttp 3.x 源码解析(一)之Interceptor 拦截器 - 云+社区 - 腾讯云
OkHttp 提交网络请求需要经过这样四个步骤:
- 初始化 OkHttpClient
- 创建 Request
- 创建 Call 对象(okHttpClient.newCall(request))
- 通过 call.excute 来发送同步请求,通过 call. enqueue 来发送异步请求
源码:
1、OkHttpClient
OkHttpClient 是通过 Builder 模式来创建实例对象的,Builder 模式常常用来复杂对象的构造,通过使用 Builder 模式可以减少构造器或方法调用传入的参数数量。
//内部构造器
public OkHttpClient() {
this(new Builder()); //调用下面的Builder()方法
}
Builder是OkHttpClient的内部类, 这里主要定义了很多参数在构建OkHttpClient时通过builde添加,如果不添加则builde内部默认定义这些参数;
如下:
dispatcher:请求分发器
interceptors; //拦截器
networkInterceptors; //网络拦截器
eventListenerFactory :Call的状态监听器
hostnameVerifier、 certificatePinner、 proxyAuthenticator、 authenticator:都是安全相关的设置
connectionPool:连接池,复用连接,我们通常将一个客户端和服务端和连接抽象为一个 connection,而每一个 connection 都会被存放在 connectionPool 中,由它进行统一的管理,例如有一个相同的 http 请求产生时,connection 就可以得到复用
2、Request
Request 同样也是使用了 Builder 模式来配置请求的url、设置get或者post请求的method 、body等等的参数.
3、Call
在创建了 OkHttpClient 和 Request 的实例对象之后,就可以通过调用 okHttpclient.newCall(request) 来创建一个 Call 对象。
OkHttpClient 的 newCall 方法实际上是调用了 RealCall(Call的实现类)的 newRealCall 方法.
@Override
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
4、同步请求 call.execute()
Call 对象就被 okHttpClient 的 newCall 方法给创建完成后,通过调用 call.execute() 来发送同步请求。
@Override
public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed"); // @1
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this); // @2
Response result = getResponseWithInterceptorChain(); // @3
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this); // 4
}
}
由上面我们可以看到:
1、根据executed标志判断当前的call是否被执行过,一个call只能执行一次,如果想要一个完全一样的 call,可以利用 all#clone 方法进行克隆。
2、利用 client.dispatcher().executed(this) 来进行实际执行,dispatcher 是刚才看到的 OkHttpClient.Builder 的成员之一,它的文档说自己是异步 HTTP 请求的执行策略,现在看来,同步请求它也有掺和。
3、最终的Response 是由getResponseWithInterceptorChain()函数获取 HTTP 返回结果,从函数名可以看出,这一步还会进行一系列“拦截”操作。
4、最后还要通知 dispatcher 自己已经执行完毕
execute 方法最关键的地方:
其一:
client.dispacher().executed(this);
client.dispacher() 方法返回了一个 dispatcher 对象,然后接着调用了 dispacher 对象的 executed 方法来发送同步请求。
最后会调用 dispatcher 的 finished() 方法来将一个请求从请求队列中移除。
其二:
response返回值的获取:
Response result = getResponseWithInterceptorChain();
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); // @1
interceptors.add(retryAndFollowUpInterceptor); // @2
interceptors.add(new BridgeInterceptor(client.cookieJar())); // @3
interceptors.add(new CacheInterceptor(client.internalCache())); // @4
interceptors.add(new ConnectInterceptor(client)); // @5
if (!forWebSocket) { //上面定义的是否为原始请求
interceptors.addAll(client.networkInterceptors()); // @6
}
interceptors.add(new CallServerInterceptor(forWebSocket)); // @7Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());return chain.proceed(originalRequest); // 8
}
由上面可知:
1、在配置 OkHttpClient 时设置的 interceptors;
2、负责失败重试以及重定向的 RetryAndFollowUpInterceptor;
3、负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的 BridgeInterceptor;
4、负责读取缓存直接返回、更新缓存的 CacheInterceptor;
5、负责和服务器建立连接的 ConnectInterceptor;
6、配置 OkHttpClient 时设置的 networkInterceptors;
7、负责向服务器发送请求数据、从服务器读取响应数据的 CallServerInterceptor。
8、开始链式调用
同步请求总结:拦截器用了责任链设计模式,它将请求一层一层向下传,知道有一层能够得到Resposne就停止向下传递,然后将response向上面的拦截器传递,然后各个拦截器会对respone进行一些处理,最后会传到RealCall类中通过execute来得到response。
5、异步请求
Okhttp 通过调用 Call 对象的 enqueue 来实现异步的网络请求。
enqueue 方法的前部分与 同步请求的 executed 方法相同,都是使用一个标志位 executed 来判断当前的 RealCall 对象是否已被执行过,如果已被执行过,则会抛出异常。
最后会调用 dispatcher 的 enqueue 方法来处理异步请求, enqueue 方法中传入了一个 封装了响应回调 callBack 的 AsyncCall 对象,AsyncCall 是 Runnable 的一个实现类。
//异步调用的方法
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
AysncCall中的execute()中的方法,同样是通过Response response = getResponseWithInterceptorChain();来获得response,这样异步任务也同样通过了interceptor,剩下的流程就和上面一样了。
6、Dispatcher
OkHttp 同步请求和异步请求都是有 dispatcher 这个分发器类来完成的。
client.dispatcher().executed(this); //同步请求
client.dispatcher().enqueue(new AsyncCall(responseCallback)); //异步请求