OkHttp 源码分析

OkHttp 使用代码实例

private static final MediaType JSON
        = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder()
            .url(url)
            .post(body)
            .build();
    // 同步调用
    Response response = client.newCall(request).execute();
    // 异步调用
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {

        }
    });
    return response.body().string();
}

源码分析

先来看 new OkHttpClient()

public OkHttpClient() {
this(new Builder());
}

public Builder() {
    // 创建了 Dispatcher 对象
    dispatcher = new Dispatcher();
    protocols = DEFAULT_PROTOCOLS;
    connectionSpecs = DEFAULT_CONNECTION_SPECS;
    eventListenerFactory = EventListener.factory(EventListener.NONE);
    proxySelector = ProxySelector.getDefault();
    cookieJar = CookieJar.NO_COOKIES;
    socketFactory = SocketFactory.getDefault();
    hostnameVerifier = OkHostnameVerifier.INSTANCE;
    certificatePinner = CertificatePinner.DEFAULT;
    proxyAuthenticator = Authenticator.NONE;
    authenticator = Authenticator.NONE;
    connectionPool = new ConnectionPool();
    dns = Dns.SYSTEM;
    followSslRedirects = true;
    followRedirects = true;
    retryOnConnectionFailure = true;
    connectTimeout = 10_000;
    readTimeout = 10_000;
    writeTimeout = 10_000;
    pingInterval = 0;
}

然后 clien.newCall(request) 创建了 RealCall 对象,这也是 OkHttp 中一个重要的类,先来分析异步执行的源码吧,因为同步执行跟异步的后半段没什么区别了。

@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
        if (executed) throw new IllegalStateException("Already Executed");
        executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    // 执行 dispatcher 的 enqueue 方法,dispatcher 是在创建 HttpClient 对象时 new 的。注意这里传过去是的 new AsyncCall(responseCallback)
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
}

AsyncCall 是实现了 NamedRunnable

public abstract class NamedRunnable implements Runnable {
    // ...
    @Override public final void run() {
        // ...
        try {
            execute();
        } finally {
            Thread.currentThread().setName(oldName);
        }
    }

    protected abstract void execute();
}

可以看到就是实现的 Runnable 接口,如果在一个线程里执行,执行的就是 execute 方法。再接着看 dispatcher 的 enqueue 方法

    synchronized void enqueue(AsyncCall call) {
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
            // 添加到执行队列
            runningAsyncCalls.add(call);
            // 在子线程执行方法,executorService 就是创建了线程池。
            executorService().execute(call);
        } else {
            // 添加到等待队列
            readyAsyncCalls.add(call);
        }
    }

AsyncCall 执行的是 execute 方法,下面接着看这里

@Override protected void execute() {
    boolean signalledCallback = false;
    try {
        // 责任链模式,链式调用的地方
        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) {
        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 {
        // 从 dispatcher 的运行队列中清除该 Runnable
        client.dispatcher().finished(this);
    }
}

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    // 添加自己定义的 interceptor
    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);
}

来一个链式调用的例子吧,

// 实际执行
public static void main(String[] args) {
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.add(new Interceptor1());
    interceptors.add(new Interceptor2());
    InterceptorChain chain = new InterceptorChain(interceptors, 0);
    chain.proceed();
}

// 执行链
public class InterceptorChain {

    private List<Interceptor> interceptors;
    private int index;

    public InterceptorChain(List<Interceptor> interceptors, int index) {
        this.interceptors = interceptors;
        this.index = index;
    }

    public void proceed() {
        if (index >= interceptors.size()) {
            System.out.println("调用完");
            return;
        }
        InterceptorChain chain = new InterceptorChain(interceptors, index+1);
        Interceptor interceptor = interceptors.get(index);
        interceptor.proceed(chain);
    }
}

// Interceptor
public interface Interceptor {
    String proceed(InterceptorChain chain);
}

public class Interceptor1 implements Interceptor {

    @Override
    public String proceed(InterceptorChain chain) {
        System.out.println("Interceptor1 start");
        chain.proceed();
        System.out.println("Interceptor1 end");
        return "Interceptor1";
    }
}

public class Interceptor2 implements Interceptor {

    @Override
    public String proceed(InterceptorChain chain) {
        System.out.println("Interceptor2 start");
        chain.proceed();
        System.out.println("Interceptor2 end");
        return "Interceptor2";
    }
}

最终的执行结果是:
Interceptor1 start
Interceptor2 start
调用完
Interceptor2 end
Interceptor1 end

可以看到 1 先执行,在 1 里面调 2 的执行,2 执行完的返回结果,1 可以再进行处理。
来一张图解释下吧
interceptor_chain

OkHttp 的调用过程用下面的图来简介一下
OkHttp_chain

猜你喜欢

转载自blog.csdn.net/hexiaosa91/article/details/81675068