簡單的使用流程
OkHttpClient okhttpclient = new OkhttpClient.Builder()
.readTimeout(READ_TIME_OUT_VALUE, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIME_OUT_VALUE, TimeUnit.SECONDS)
.build();
Request.Builder builder = new Request.Builder();
Request request = builder.url(httpUrl).get().build();
Call call = okhttpclient.newCall(request);
try{
Response response = call.execute();
} catch (IOException e){
//異常處理
}
從newCall出發深入源碼
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
我們繼續查看RealCall.newRealCall
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;
}
RealCall
是Call
的一個實現,Response
是call
的execute()
方法得到的,我們接下來繼續跟蹤RealCall
的execute
方法。
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
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);
}
}
方法中我們可以看到Response
通過getResponseWithInterceptorChain()
得到,下面是其源碼:
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 (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
經過中間的一系列步驟,最終返回的是chain.proceed(originalRequest)
,那我們繼續跟蹤查看RealInterceptorChain
并找到proceed
方法的內容:
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) 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.httpCodec != null && !this.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.httpCodec != 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, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, 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 (httpCodec != null && index + 1 < interceptors.size() && next.calls != 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);
最終的請求結果是由interceptor.intercept()
得到的,我們回想上一個getResponseWithInterceptorChain
方法中所添加的一系列Interceptor
我們根據變量或類名稱推測建立連接的是ConnectInterceptor
,我們查看一下它的具體內容:
/** Opens a connection to the target server and proceeds to the next interceptor. */
/** 打開一個到目標服務器的連接,并進入下一個interceptor.*/
public final class ConnectInterceptor implements Interceptor {
public final OkHttpClient client;
public ConnectInterceptor(OkHttpClient client) {
this.client = client;
}
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}
代碼中可以看到,OkHttpClient
通過RealConnection connection = streamAllocation.connection();
建立了一個連接。
我們查看RealConnection
類:
public final class RealConnection extends Http2Connection.Listener implements Connection {
private static final String NPE_THROW_WITH_NULL = "throw with null exception";
private static final int MAX_TUNNEL_ATTEMPTS = 21;
private final ConnectionPool connectionPool;
private final Route route;
// The fields below are initialized by connect() and never reassigned.
/** The low-level TCP socket. */
private Socket rawSocket;
/**
* The application layer socket. Either an {@link SSLSocket} layered over {@link #rawSocket}, or
* {@link #rawSocket} itself if this connection does not use SSL.
*/
private Socket socket;
......
}
我們在代碼中找到了比較重要的信息Socket
,基本可以證明,Okhttp3
的底層是Socket
實現的。
到這里不妨回憶一下我們所經歷的步驟,一切都與RealInterceptorChain
有很大的關系,OkhttpClient
通過不斷地執行它的proceed
方法,反復的修飾了我們的網絡請求。
經過百度搜索,我發現這樣一篇文章Okhttp3源碼分析
終于明白了它文章開篇的這個Okhttp請求流程圖:
至此,我們了解了Okhttp3
的簡單實用,以及它的底層是通過Socket
實現的,并且認識了它的攔截器鏈RealInterceptorChain
,下一步從異步與多線程入手,再次學習Okhttp3
源碼。