源码系列--OkHttp
2021-03-18 07:23
标签:final stack sse sync rri 请求 add tor assert OkHttp官网地址:https://square.github.io/okhttp/ 用法如下:(get请求) Github下载源码地址https://github.com/square/okhttp 4.x以上的版本都大部分更新为kotlin了,可以更改分支下载3.x的版本来看 一。先来看第一步构造函数 源码: Builder()中就是初始化了一堆变量,没啥东西 二。来看get请求 源码:找内部类Builder的构造函数 源码:接着找Headers的内部类Builder,暂时构造了一个变量,还没有做什么 三。下面是执行.url方法,当然是Request内部类Builder的url方法,url暂定为String 源码: 前面是加前缀,后面去到HttpUrl里去 HttpUrl的内部类Builder的构造函数 encodedPathSegments是一个ArrayList HttpUrl的内部类Builder的parse方法就是一连串的参数解析,大家可以看源码 最后一个build()方法 这个HttpUrl的带参构造函数中也是一堆变量的初始化 回到Request内部类Builder的url方法 接着是Request内部类Builder的build方法 Request的带参构造函数 四。接下来很重要了,是执行请求 OkHttpClient中的newCall方法 进到RealCall中的newRealCall方法 构造函数不用管,进去Transmitter中的构造函数 其中这个Internal.instance.realConnectionPool(client.connectionPool())可以找到OkHttpClient的static代码块执行后返回了一个RealConnectionPool RealConnectionPool一看就知道是0个核心线程,最大值个非核心线程的线程池;这里还出现了一个Deque双端队列,即队列的升级版,两个端口都可以进出元素,更加灵活 最后就是RealCall的execute方法了,注意RealCall里有个内部类AsyncCall也有execute方法,注意不要搞混了 client.dispatcher().executed(this)执行的是 runningSyncCalls就是我们上面提到的Deque双端队列 下面就是最最核心的getResponseWithInterceptorChain方法 RetryAndFollowUpInterceptor重试和跳转拦截器 BridgeInterceptor桥接拦截器,即加请求头和去响应头 CacheInterceptor缓存拦截器 ConnectInterceptor连接拦截器 CallServerInterceptor调用服务拦截器 List添加好全部Interceptor之后,执行chain.proceed(originalRequest)来到RealInterceptorChain中的proceed方法 Interceptor interceptor = interceptors.get(index); 一开始传入的index为0,就是从第一个拦截器开始执行每个拦截器的intercept方法,index逐次+1 每个拦截器里都调用chain.proceed,这样所有的拦截器就形成链条。这里每个拦截器的作用就不讲了 欢迎关注我的微信公众号:安卓圈
源码系列--OkHttp 标签:final stack sse sync rri 请求 add tor assert 原文地址:https://www.cnblogs.com/anni-qianqian/p/12774332.htmlpackage okhttp3.guide;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class GetExample {
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
public static void main(String[] args) throws IOException {
GetExample example = new GetExample();
String response = example.run("https://raw.github.com/square/okhttp/master/README.md");
System.out.println(response);
}
}
OkHttpClient client = new OkHttpClient();
public OkHttpClient() {
this(new Builder());
}
new Request.Builder()
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");
// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}
return url(HttpUrl.get(url));
}
public static HttpUrl get(String url) {
return new Builder().parse(null, url).build();
}
public Builder() {
encodedPathSegments.add(""); // The default path is ‘/‘ which needs a trailing space.
}
public HttpUrl build() {
if (scheme == null) throw new IllegalStateException("scheme == null");
if (host == null) throw new IllegalStateException("host == null");
return new HttpUrl(this);
}
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
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);
}
Response response = client.newCall(request).execute()
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
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.transmitter = new Transmitter(client, call);
return call;
}
public Transmitter(OkHttpClient client, Call call) {
this.client = client;
this.connectionPool = Internal.instance.realConnectionPool(client.connectionPool());
this.call = call;
this.eventListener = client.eventListenerFactory().create(call);
this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
}
private static final Executor executor = new ThreadPoolExecutor(0 /* corePoolSize */,
Integer.MAX_VALUE /* maximumPoolSize */, 60L /* keepAliveTime */, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp ConnectionPool", true));
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.timeoutEnter();
transmitter.callStart();
try {
client.dispatcher().executed(this);
return getResponseWithInterceptorChain();
} finally {
client.dispatcher().finished(this);
}
}
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.exchange != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (exchange != null && index + 1 ) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn‘t null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
Response response = interceptor.intercept(next);