OkHttp 3.12.0源码分析

主要参考文章:
1.Okhttp的基本使用
2.Okhttp主流程源码分析

Okhttp 3.12.0 使用例子

String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
        .url(url)
        .get()//默认就是GET请求,可以不写
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d("ziq", "onFailure: ");
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d("ziq", "onResponse: " + response.body().string());
    }
});

1、初始化

建造者模式,public OkHttpClient() { this(new Builder());} 初始化了一些配置信息:支持协议、任务分发器(其内部包含一个线程池,执行异步请求)、连接池(其内部包含一个线程池,维护connection)、连接/读/写超时时长等信息。

public Builder() {
    dispatcher = new Dispatcher();//任务调度器
    protocols = DEFAULT_PROTOCOLS;//支持的协议 Protocol.HTTP_2, Protocol.HTTP_1_1
    connectionSpecs = DEFAULT_CONNECTION_SPECS;
    eventListenerFactory = EventListener.factory(EventListener.NONE);
    proxySelector = ProxySelector.getDefault();
    if (proxySelector == null) {
        proxySelector = new NullProxySelector();
    }
    cookieJar = CookieJar.NO_COOKIES;
    socketFactory = SocketFactory.getDefault();
    hostnameVerifier = OkHostnameVerifier.INSTANCE;//根据地址与证书 进行校验X509Certificate
    certificatePinner = CertificatePinner.DEFAULT;
    proxyAuthenticator = Authenticator.NONE;//身份验证
    authenticator = Authenticator.NONE;//身份验证
    connectionPool = new ConnectionPool();//连接池
    dns = Dns.SYSTEM;
    followSslRedirects = true;
    followRedirects = true;
    retryOnConnectionFailure = true;
    callTimeout = 0;
    connectTimeout = 10_000;
    readTimeout = 10_000;
    writeTimeout = 10_000;
    pingInterval = 0;
}

下面列出 Dispatcher 的主要分析部分

//Dispatcher.java
public final class Dispatcher {
private int maxRequests = 64;//最大请求数量
private int maxRequestsPerHost = 5;//每台主机最大的请求数量
private @Nullable Runnable idleCallback;
private @Nullable ExecutorService executorService;//线程池
private final Deque readyAsyncCalls = new ArrayDeque<>();//等待队列
private final Deque runningAsyncCalls = new ArrayDeque<>();//异步运行中队列
private final Deque runningSyncCalls = new ArrayDeque<>();//同步运行中队列

public synchronized ExecutorService executorService() {
    if (executorService == null) {
        executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
}

。。。
void enqueue(AsyncCall call) {
    synchronized (this) {
        readyAsyncCalls.add(call);//添加到异步运行队列中
    }
    promoteAndExecute();//将 readyAsyncCalls中的call 添加到 runningAsyncCalls并运行
}

private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));
    List executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
        for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
            AsyncCall asyncCall = i.next();
        //正在运行的任务数是否大于 64
            if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        //对应主机 的 正在运行的任务数是否大于 5
            if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
            i.remove();
            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;
}

。。。
}

2、生成call 并 请求

//OkHttpClient.java
@Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
}

//RealCall.java
new RealCall(client, originalRequest, forWebSocket);

@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));
}

那么从dispatcher的代码中可知道,call直接加入到 readyAsyncCalls队列中,然后 在promoteAndExecute方法中判断是否 可以执行 readyAsyncCalls中的任务,如果可以则 把任务加入到runningAsyncCalls ,并 到线程池中执行。

3、执行call

asyncCall.executeOn(executorService());
AsyncCall extends NamedRunnable implements Runnable
,所以运行run() ->execute() ;

final class AsyncCall extends NamedRunnable {
。。。
@Override protected void execute() {
    boolean signalledCallback = false;
    timeout.enter();
    try {
//1、进过一系列拦截器后,返回结果
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
            signalledCallback = true;
            responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
            signalledCallback = true;
            responseCallback.onResponse(RealCall.this, response);
        }
    } catch (IOException e) {
        e = timeoutExit(e);
        if (signalledCallback) {
            // Do not signal the callback twice!
            Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
            eventListener.callFailed(RealCall.this, e);
            responseCallback.onFailure(RealCall.this, e);
        }
    } finally {
//2、结束当前call,运行未执行且符合条件的call
        client.dispatcher().finished(this);
    }
}

}

4、Interceptor拦截器

到了这里,到达了okhttp最核心的部分, Interceptor,采用了责任链的设计模式

4.1client.dispatcher().finished(this);
//Dispatcher.java
private  void finished(Deque calls, T call) {
    Runnable idleCallback;
    synchronized (this) {
    if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
        idleCallback = this.idleCallback;
    }
    boolean isRunning = promoteAndExecute();
    if (!isRunning && idleCallback != null) {
        idleCallback.run();
    }
}

可以看到,移除call后,又回到 一开始 的promoteAndExecute() 方法,去把readyAsyncCalls中的call 拿出来运行。

4.2 责任链

Response response = getResponseWithInterceptorChain();进过一系列拦截器后,返回结果

//RealCall.java
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
    List 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);
}

添加的各Interceptor,分别负责功能:
client.interceptors() 用户自定义的Interceptor,能拦截到所有的请求
RetryAndFollowUpInterceptor 负责失败重连和重定向相关
BridgeInterceptor 负责配置请求的头信息,比如Keep-Alive、gzip、Cookie等可以优化请求
CacheInterceptor 负责缓存管理,使用DiskLruCache做本地缓存,CacheStrategy决定缓存策略
ConnectInterceptor 开始与目标服务器建立连接,获得RealConnection
client.networkInterceptors() 用户自定义的Interceptor,仅在生产网络请求时生效
CallServerInterceptor 实际网络请求的地方。

递归实现:
1、RealInterceptorChain.proceed(...) 为开头,会生成 下一步的RealInterceptorChain next1,与当前的RealInterceptorChain参数一样,区别是index 加1了,所以会调用 下一级 拦截器的interceptor1.intercept(next)
2、interceptor1.intercept(next)调用 下一个链 next1.proceed(...)方法
3、next1.proceed(...)调用下一个interceptor2.intercept(next) 形成 递归
4、最后的拦截器是 CallServerInterceptor,返回response,然后一级一级返回response。

//RealInterceptorChain.java
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,RealConnection connection)throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();
    calls++;
    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 (this.httpCodec != null && calls > 1) {
        throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must call proceed() exactly once");
    }
//1、生成 下一步的RealInterceptorChain,与当前的RealInterceptorChain参数一样,区别是index 加1 了
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
 //2、Interceptor interceptor内会调用 next.proceed(...) 又回到这里的第一步,再生成一个chain 形成递归
    Response response = interceptor.intercept(next);
//结束递归

    if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
        throw new IllegalStateException("network interceptor " + interceptor
        + " must call proceed() exactly once");
    }
    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;
}

各个拦截器部分细节描述:

拦截器 描述
RetryAndFollowUpInterceptor 生成 StreamAllocation 实例,后面的拦截器使用
BridgeInterceptor 添加header参数
CacheInterceptor 默认是没有缓存的,全都是直接网络请求。
ConnectInterceptor 利用上面 的StreamAllocation 建立 HttpCodec、RealConnection实例从connectionPool 寻找是否有RealConnection,有就直接赋值给StreamAllocation 中的connection 找不到就result = new RealConnection(connectionPool, selectedRoute);新建,赋值给StreamAllocation并且缓存到connectionPool
CallServerInterceptor 使用前面其他拦截器生成的 StreamAllocation , RealConnection, HttpCodec;
而HttpCodec 中使用okio 通过Socket传输数据,网络请求。

你可能感兴趣的:(OkHttp 3.12.0源码分析)