OKhttp源码分析

版本:com.squareup.okhttp3:okhttp:3.11.0

1、call.eventListener = client.eventListenerFactory().create(call)
建立连接(tcp、tls)

2、client.dispatcher().enqueue(new AsyncCall(responseCallback));

dispatcher(): 处理线程

enqueue(..): 成立的情况下就会去让线程管理去管理线程,让 call 在后台去执行,
如果不成立则会添加到 readyAsyncCalls 队列中,一个待用的队列,随时可能发送请求

AsyncCall:会调用父类run方法中的 execute(),实现在 RealCall 的 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 {
        client.dispatcher().finished(this);
      }
    }
  }

3、okhttpclient配置项

 final Dispatcher dispatcher;线程调度管理器

  final @Nullable Proxy proxy;设置代理服务器,如果我们无法访问或访问失败我们的目标服务器,可以交给代理服务器去帮我们访问想要访问的目标服务器

  final List<Protocol> protocols; 所支持的 http 协议版本

  final List<ConnectionSpec> connectionSpecs;配置使用http还是https;包括SSL和TLS版本的选择配置
  final List<Interceptor> interceptors;
  final List<Interceptor> networkInterceptors;
  final EventListener.Factory eventListenerFactory;
  final ProxySelector proxySelector;

  final CookieJar cookieJar;cookie存储器

  final @Nullable Cache cache;http的cache

  final @Nullable InternalCache internalCache;

  final SocketFactory socketFactory;创建tcp端口

  final @Nullable SSLSocketFactory sslSocketFactory;创建SSL端口

  final @Nullable CertificateChainCleaner certificateChainCleaner;整理服务器传输而来的证书

  final HostnameVerifier hostnameVerifier;用于https中,验证对方服务器的host

  final CertificatePinner certificatePinner;做自签名

  final Authenticator proxyAuthenticator;Head中添加Authorizaion,访问权限配置
  final Authenticator authenticator;

  final ConnectionPool connectionPool;连接池

  final Dns dns;
  final boolean followSslRedirects;当遇到http与https互相跳转,是否跳?
  final boolean followRedirects;如果遇到需要跳转的情况下,是否去跳转,比如返回3xx,默认是true
  final boolean retryOnConnectionFailure;请求失败,是否重新连接
  final int connectTimeout;tcp链接时间
  final int readTimeout;下载等待响应时间
  final int writeTimeout;写入响应时间
  final int pingInterval;针对wbsocket的,多久ping一次,客户端发送ping,服务端发送pong
//自签名
public void mySingn() {
        String hostname = "hencoder.com";
        CertificatePinner certificatePinner = new CertificatePinner.Builder()
//                .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
                .add(hostname, "sha256/rZ/xwvaoWYYzhWGtTUCUNO07mHKM82JCfdvWZm1Z7nU=")
                .add(hostname, "sha256/GI75anSEdkuHj05mreE0Sd9jE6dVqUIzzXRHHlZBVbI=")
                .add(hostname, "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=")
                .build();
        OkHttpClient client = new OkHttpClient.Builder()
                .certificatePinner(certificatePinner)
                .build();

        Request request = new Request.Builder()
                .url("https://" + hostname)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i("qqq","onFailure...");

                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.i("qqq","onSuccess...");

            }
        });
    }

4、分析execute中的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);
  }

作用:将准备好的请求去做网络请求,然后得到响应(response)

image.png

责任链模式

chain.proceed 的流程如上图。

先做请求的前置工作,然后调用proceed()方法,如果proceed()方法返回成功,则会接着去做响应后置工作;在proceed()方法执行过程中,又会去调用下一个拦截器的请求前置工作、proceed()、响应后置工作。。。

client.interceptors():做拦截工作,可以在请求前做一些处理,或者在请求之后做一些处理

retryAndFollowUpInterceptor:用于网络的重试工作

BridgeInterceptor:封装request和response的过滤器,各种http参数的设置,Content-Type、User-Agent等等

CacheInterceptor:如果已有的cache信息,还在保存期内,那么就直接使用cache中的数据,则不会再去做接下来的网络请求

ConnectInterceptor:在该拦截器中与TCP、HTTPS的TLS来做交互,即建立一个TCP连接或者在TCP的连接上再叠加一个TLS连接。(该拦截器没有后置工作)

client.networkInterceptors():配置 OkHttpClient 时设置的 networkInterceptors,一般很少用,主要用 client.interceptors()

CallServerInterceptor:负责向服务器发送请求数据、从服务器读取响应数据(实际网络请求)

image.png

优点:
可以看到,这里首先new了一个Interceptor的ArrayList,然后分别加入了各种各样的Interceptor,所以当我们默认创建okHttpClient时,okHttp默认会给我们实现这些过滤器,每个过滤器执行不同的任务,这个思想太屌了有木有,每个过滤器负责自己的任务,各个过滤器间相互不耦合,高内聚,低耦合,对拓展放开巴拉巴拉等一系列设计思想有木有,这里可以对比一下Volley源码中的思想,Volley的处理是将缓存,网络请求等一系列操作揉在一起写,导致用户对于Volley的修改只能通过修改源码方式,而修改就必须要充分阅读理解volley整个的流程,可能一部分的修改会影响全局的流程,而这里,将不同的职责的过滤器分别单独出来,用户只需要对关注的某一个功能项进行理解,并可以进行扩充修改,一对比,okHttp在这方面的优势立马体现出来了。这里大概先描述一下几个过滤器的功能

面试题

1、okhttp 的原理。先重定向再查缓存?请求池?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容