okhttp源码解读--上篇(okhttpclient参数,enqueue/execute调用)

前两天刚刚把Retrofit的源码看完,发现对于底层的请求调用还是通过okhttp来进行的.
现在来研究一下okhttp的源码.
由于okhttp比retrofit细节,结构上要更复杂.预期以3个篇幅来进行讲解.
分别是:
上篇:okhttpclient的参数,调用.
中篇:getResponseWithInterceptorChain
下篇:各个Interceptor的作用和自定义Interceptor

okhttp

画个重点.
我们看完Retrofit后知道它的核心代码是 Proxy.newProxyInstance()
那么OkHttp的重点是什么呢?
getResponseWithInterceptorChain()

本次源码解读将基于OkHttp最新版本3.13.1进行.
我将以看过okhttp源码后的视角来写这篇流水账博客.


1.okhttp的用法.

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
          .url("https://api.github.com/")
          .build();

okHttpClient.newCall(request).enqueue(new Callback() {
         @Override
         public void onFailure(Call call, IOException e) {
                System.out.println("请求失败");
         }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
                System.out.println("请求成功");
         }
});

最常见的用法,我们先创建了一个OkHttpClient,然后通过Builder模式创建了一个Request,再将Request传到newCall()内,调用enqueue()/execute()即可.

这段基础调用代码,我们主要学习一下3个内容.

  1. OkHttpClient
  2. newCall
  3. enqueue/execute

2. OkHttpClient

这个主要的类,我们看一下全局的变量,几十个呢.
挑几个重点看一下吧.
反正看得懂就看,看不懂就关掉,千万别一棵树吊死了.(完全看不懂的,我就不写出来了,23333)

  • Dispatcher dispatcher
    这玩意主要功能就字面意思…是一个调度器.
    Flux的diapatcher负责全局调度传递Action.那我们看看okhttp的.
    okhttp源码解读--上篇(okhttpclient参数,enqueue/execute调用)_第1张图片
    最大请求数量64、同一个Host最大请求数量5、idleCallback(闲置的callback)、executorService(线程池)、3个queue(分别是准备好的异步queue,正在运行的异步queue,正在运行的同步queue).
    okhttp内,dispather的作用是调度传递各种call,如RealCall/AsynCall.

    具体的作用等待看一下后续的,再思考具体的作用.

  • List protocols
    点进去看一下这个Protocol,
    emmm…
    HTTP_1_0、HTTP_1_1、SPDY_3、HTTP2、H2_PRIOR_KNOWLEDGE、QUIC
    下面还有一个get方法,传入对应的String protocol,给你匹配对应的Hypertext Transfer Protocol (超文本协议).
    我知道的也就http1.0、http1.1、spdy、http2.0了,其他的是什么鬼.
    反正知道了大概这就是okhttp支持的协议了.(我们常用的也就是http1.1罢了)

  • List connectionSpecs
    点进去看一下ConnectionSpec,
    CipherSuite !!!
    TLS打头的…
    这妥妥的就是HTTPS连接建立,TLS安全层 客户端和服务端Client Hello/Service Hello 使用的非对称加密/对称加密/HASH算法的 支持合辑了.

  • List interceptors/List networkInterceptors
    这2个Interceptor涉及到okhttp的最核心的东西getResponseWithInterceptorChain,后面再分析.

  • CookieJar cookieJar
    CookieJar这个东西,我还是认为有必要提一句的.
    okhttp源码解读--上篇(okhttpclient参数,enqueue/execute调用)_第2张图片
    核心的就这2个方法了,
    当初最开始使用这个的时候,我也纠结过这是啥玩意.
    其实是很简单
    完全可以自己实现一下CookieJar,然后自己弄一个Map存储一下.

CookieJar I_NEED_COOKIES = new CookieJar() {

            Map> mCookie = new HashMap();

            @Override
            public void saveFromResponse(HttpUrl url, List cookies) {
                mCookie.put(url.toString(), cookies);
            }

            @Override
            public List loadForRequest(HttpUrl url) {
                return mCookie.get(url.toString());
            }
        };

和Retrofit的ServiceMethodCache,loader.ProxyCache一样,有就直接拿,没有就存进去.

  • CertificatePinner certificatePinner
    这个东西也提一嘴.当在OkHttpClient创建时,可以通过额外添加一个CertificatePinner,使其在访问指定host时,直接校验本地写死的证书公钥,不进行多层证书和签名验证
OkHttpClient newOkHttpClient = new OkHttpClient.Builder()
                .certificatePinner(
                        new CertificatePinner.Builder().add("指定的host","证书公钥(sha256/XXXX)").build())
                .build();

对了,如果不记得证书公钥,可以直接随便写一个,log有返回正确的哟…

  • Other
    剩下的一些内容,要么就是很直观,看一样名字就能够了解的,要么就是我不会的,我就不班门弄斧了.

3. newCall

点进去看看,复读机
emmm…

RealCall.newRealCall(this, request, false /* for web socket */);

一个参数变3个参数,一个okhttpclient,一个传入的request,一个websocket.

临时插播一下webSocket的信息.
据我所知,webSocket的使用场景是那种需要 长连接,服务器频繁刷新数据的场景.比如说 金融?
听朋友说,智能家居方面也用这玩意了,最近面试问的还挺多?
完全没用过啊,开坑学习,研究预定!!!

再看看newRealCall().其实就是创建了一个RealCall.

RealCall call = new RealCall(client, originalRequest, forWebSocket);

OK,期待一下enqueue/execute在这个RealCall里面的调用吧.


4.enqueue/execute

终于到了关键的请求部分了.
让我们点进去看看 复读机.png

  • execute
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();

关键的代码就2行…
调用dispatcher的executed()方法,将这个包装着request的RealCall放到了runningSyncCalls这个queue里面去了.
然后就直接通过getResponseWithInterceptorChain()获取到了response…
这就结束了, 就是辣么简单.
有的人可能就要说了.不对啊,不是说okhttp请求是自己实现的socket连接么,
哪里连接了socket?又在哪里接受到了数据呢?咋就直接返回了?

  • enqueue
client.dispatcher().enqueue(new AsyncCall(responseCallback));

先看看这个dispatcher.enqueue做了什么.
1.先将这个包装着request的RealCall放到了readyAsyncCalls这个euque里面去了.
2.调用promoteAndExecute();
3.检查当前请求数量和同一Host下请求数量,将readyAsyncCalls的call放到runningAsyncCalls内.
4.使用一个叫做AsyncCall调用executeOn()
okhttp源码解读--上篇(okhttpclient参数,enqueue/execute调用)_第3张图片

再看看enqueue传入的参数,刚好也是一个AsyncCall,巧了.

在这个AsyncCall内调用executeOn,也就是启用线程池来调用这个AsyncCall.
okhttp源码解读--上篇(okhttpclient参数,enqueue/execute调用)_第4张图片
AsyncCall继承了NamedRunnable.看一眼这个runnbale的run(),然来调用的是execute();
execute()也通过getResponseWithInterceptorChain()拿到了response.

最后将response,通过在MainActivity里面创建的CallBack回调至Activity内.


总结.

okhttp的整体调用(enqueue/execute)逻辑,基本就是这样了.
发现最核心的HTTP请求处理部分都在getResponseWithInterceptorChain()里面了.

下一篇将开始讲解这个核心.

你可能感兴趣的:(Android,okhttp,源码解读,okhttpclient,enqueue,execute)