OKHttp同步网络请求原理分析(图文并茂,看困包赔)

Hello,All,我是来自58同城的一名Android开发工程师,在58集团从事APP的开发工作。在日常的工作和学习过程中我经常会碰到一些好玩的和有意思的Android小知识点,有些知识可能都从未注意到过。通过一个多月的收集和整理,我发现通过不断地记录这些问题达到了非常好的复习效果,从而帮助了工作上的持续进步,今天我也是把平时收集到的这些东西发出来供大家一起学习,共同成长,如果感觉好,欢迎点击右侧的留言、点赞、加关注,您的支持是我最大的动力。

PS:关注,私信我,帮你内推58,常年招聘前端,移动端,后端,算法。

也欢迎关注我的公众号,在这里可以找到我,同时,这里会不定期地推送一些时下最热门的技术文章和互联网行业工作心路历程

                                                                            


OKHTTP是现在最流行的Android轻量级网络请求框架,他以其简洁的请求流程和使用方式,成功地干掉了Volley等老牌网红框架,并且吸引着越来越多的app开发者加入用户阵营。

同样,在58中台的Passport SDK中也应用到了OKHTTP技术来处理登录,账号找回等前后端交互流程。

为了能够更加自如地运用他,今天我们就来详细的了解一下OKHTTP到底是怎么帮我们完成复杂的网络请求过程。并且,通过学习他的处理流程,是否可以自己搭建一个类似的处理框架来提供给别人使用。

先从最经典的网络请求开始

OkHttpClient okHttpClient = new OkHttpClient();

 先new了一个okHTTPClient对象出来,我们来看看okHttpClient里面都做了些什么

 通过默认的构造方法,我们看到最终是调用到了OkhttpClient.Builder并且new了一个Builder出来传入到了OkHttpClient

其实很多时候我们从一个类的构造函数当中就可以看出来这个类的大致作用,尤其是这种Builder建造者设计模式,我们可以看到,在OKHTTPClient的Builder中可以配置很多client端的处理需求,如:是否重试,超时时间,配置dns,配置HTTP协议版本等操作,这些参数都会在请求的处理当中被使用到。

好,我们接着往下看:

        Request.Builder okRequestBuilder = new Request.Builder().url(builder.build());

 这里是进行了request的一个配置过程,通过查看Request的源码我们可以发现,这里同样是完成了一个请求参数的配置过程:

通过Android Studio的Structure功能我们可以很清楚地看到Request类的结构,其中,我们可以通过他的Builder来配置body,header,tag,url等请求参数

接下来

            Response response = client.newCall(okRequestBuilder.build()).execute();

我们可以看到,这一条语句才是真正地发出了网络请求,其中,newCall调用之后其实是返回了一个RealCall对象,然后调用了他的execute()方法来完成同步请求,好,我们来看源码:

可以看到,在标注为1的地方调用了一个eventListener对象的callStart方法,这个方法是做什么用的呢?让我们进入到他的实现类来看看

可以看到,EventListener其实是一个抽象类,但其中预留了很多的回调函数,包括callStart,dnsStart等等功能性函数。看到这是不是有种似曾相识的感觉?

没错,我们在配置Request的时候也配置过这些参数进来,这样,在网络请求的各个阶段,OKHTTP就会通知我们网络请求的各个状态。当然,这里的create使用的是建造者设计模式,他的实现必须是由我们用户自己来定义的。

在源码中标记为2的地方我们能够看到,Request最终是通过调用调度器Dispatcher的executed来把当前的对象进行了一个传入,注意,这里是executed方法,为什么不是execute呢?好,我们来看看他的实现

通过实现我们可以看到,最终是将这个请求加入到了一个ArrayDeque双端队列中。ArrayDeque是什么鬼?为什么不是LinkedList?我们先留点神秘,后面再来进行详细的探讨。

紧接着,就进入到了拦截器的处理阶段

这里可以看到,okhttp先是构建了一个数组容器,然后先将用户自定义添加的各种拦截器进行入队操作,注意,这里的拦截器其实是有先后顺序的。

初始化完拦截器容器就进入到了责任链处理阶段,这里我们能够看到,这个操作是委托给了一个叫RealInterceptorChain的Interceptor实现类来进行的(RealInterceptorChain是Interceptor.Chain的唯一实现),并最终调用了他的proceed方法。让我们来看看proceed方法里到底做了些什么。

 public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

。。。
    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

    。。。

    return response;
  }

可以看到,进入到这个方法之后首先是进行了一个计数自增的操作,这个自增的标志其实是用来控制拦截器容器里各种拦截器的访问次序的。然后,OKHttp通过创建一个RealInterceptorChain的next对象并且获取到了容器中的相应index位置的拦截器,最后,通过调用interceptor的intercept方法来实现了拦截器内定义方法的执行,为了整体篇幅的考虑,我们在后续的文章中再来对这几个拦截器进行详细的解析。

好,经过拦截器的处理之后,最终是得到了response对象,也就是我们的result。

到了这里,OKHTTP的同步网络请求过程就分析完了,可以看到,其中最核心的就要数对相关设计模式的应用了,我们来总结一下:

OkHttpClient及Request的配置过程:Builder建造者设计模式

EventListener的构建过程:Factory工厂模式

RealInterceptorChain的处理过程:责任链设计模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章