build.gradle
中添加组件: implementation 'com.squareup.okhttp3:okhttp:3.14.2' 复制代码
//注意这里,一般我们用单例,Okhttp官方描述如果不用单例,线程管理等都失效了,浪费开销 /*Http performs best when you create a single {@code OkHttpClient} instance and reuse it for * all of your HTTP calls. This is because each client holds its own connection pool and thread * pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a * client for each request wastes resources on idle pools. */ OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); return response.body().string(); } 复制代码
通过okhttp源码分析,直接创建的 OkHttpClient对象并且默认构造builder对象进行初始化
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory { 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; ... this.hostnameVerifier = builder.hostnameVerifier; this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner( certificateChainCleaner); this.proxyAuthenticator = builder.proxyAuthenticator; this.authenticator = builder.authenticator; this.connectionPool = builder.connectionPool; this.dns = builder.dns; this.followSslRedirects = builder.followSslRedirects; this.followRedirects = builder.followRedirects; this.retryOnConnectionFailure = builder.retryOnConnectionFailure; this.connectTimeout = builder.connectTimeout; this.readTimeout = builder.readTimeout; this.writeTimeout = builder.writeTimeout; this.pingInterval = builder.pingInterval; } } 复制代码
一般如下:
Request request = new Request.Builder().url("url").build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } }); 复制代码
初始化构建者模式和请求对象,并且用URL替换Web套接字URL。
public final class Request { public Builder() { this.method = "GET"; this.headers = new Headers.Builder(); } public Builder url(String url) { ...... // 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); } HttpUrl parsed = HttpUrl.parse(url); ...... return url(parsed); } public Request build() { ...... return new Request(this); } } 复制代码
主里主要是调用了 newCall
方法,我们跟进去看看:
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory { @Override public Call newCall(Request request) { return new RealCall(this, request, false /* for web socket */); } } 复制代码
发现去 new RealCall
了,我们跟到 RealCall
看看:
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) { this.client = client; this.originalRequest = originalRequest; this.forWebSocket = forWebSocket; } 复制代码
可以看到只是初始化一些成员变量,真正的调用是 RealCall
里面的 enqueue(添加到队列)/execute(立即执行)
方法,我们看看:
void enqueue(AsyncCall call) { synchronized (this) { /** Ready async calls in the order they'll be run. */ //private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); // readyAsyncCalls是一个双端队列,把该call加入到准备的队列里 readyAsyncCalls.add(call); // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to // the same host. if (!call.get().forWebSocket) { AsyncCall existingCall = findExistingCallWithHost(call.host()); if (existingCall != null) call.reuseCallsPerHostFrom(existingCall); } } promoteAndExecute(); } 复制代码
上面不难发现最终调用了 promoteAndExecute()
,我们跟进去看看:
/** * Promotes eligible calls from {@link #readyAsyncCalls} to {@link #runningAsyncCalls} and runs * them on the executor service. Must not be called with synchronization because executing calls * can call into user code. * * @return true if the dispatcher is currently running calls. */ private boolean promoteAndExecute() { assert (!Thread.holdsLock(this)); List<AsyncCall> executableCalls = new ArrayList<>(); boolean isRunning; synchronized (this) { for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) { AsyncCall asyncCall = i.next(); if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity. // 最大的线程请求的时候,不再添加, maxRequests默认值是:64 if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity. // 最大的DNS解析为:5 i.remove(); asyncCall.callsPerHost().incrementAndGet(); executableCalls.add(asyncCall); runningAsyncCalls.add(asyncCall); } isRunning = runningCallsCount() > 0; } // 循环执行 for (int i = 0, size = executableCalls.size(); i < size; i++) { AsyncCall asyncCall = executableCalls.get(i); asyncCall.executeOn(executorService()); } return isRunning; } 复制代码
有一个问题, enqueue
是拿到Reponse的? 它和 execute
区别?
带着问题,我们可以在 RealCall
中可以发现 final class AsyncCall extends NamedRunnable
这个 NamedRunnable
是什么?
/** * Runnable implementation which always sets its thread name. */ public abstract class NamedRunnable implements Runnable { protected final String name; public NamedRunnable(String format, Object... args) { this.name = Util.format(format, args); } @Override public final void run() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(name); try { execute(); } finally { Thread.currentThread().setName(oldName); } } protected abstract void execute(); } 复制代码
根据源码发现它原来是一个 runable
,并且抽象了 execute
,所以 execute
就是 enqueue
去执行的核心方法,那么我就可以看到 execute
方法的实现:
@Override protected void execute() { boolean signalledCallback = false; transmitter.timeoutEnter(); try { Response response = getResponseWithInterceptorChain(); signalledCallback = true; 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 { responseCallback.onFailure(RealCall.this, e); } } finally { client.dispatcher().finished(this); } } 复制代码
实际上跟 execute
方法一样,都是调用了 getResponseWithInterceptorChain
,跟进去看看:
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); interceptors.addAll(client.interceptors());// 1.添加自定义的拦截器 interceptors.add(new RetryAndFollowUpInterceptor(client));// 2.重试拦截 interceptors.add(new BridgeInterceptor(client.cookieJar())); // 3.Build一个适配的Request interceptors.add(new CacheInterceptor(client.internalCache()));// 4.添加缓存拦截器 interceptors.add(new ConnectInterceptor(client)); // 5.ConnectInterceptor验证Get请求 if (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); // 6.非Websocket下创建的自定义网络拦截器 } interceptors.add(new CallServerInterceptor(forWebSocket)); // 7. 真实的IO访问,使用了OKIO库去实现的 Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0, originalRequest, this, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis()); ..... return response; } 复制代码
从上面的设计模式可以看出来OKHttp使用了 责任链
的设计模式. 至此流程已经完毕. 下面学习一些优秀的细节.