其实你可以读懂OKHttp3的源码
来源:互联网 发布:淘宝运营教材 编辑:程序博客网 时间:2024/05/16 13:06
因为公司的项目中使用了的Retrofit2+OK3,所以有时间闲下来还是有必要研究一下它的源码,本来就抱着试试看的心态,项目上线了,休息休息也是可以的,呵呵。所以就走马观花的去读了一遍,写下自己的分享,作为一个新人,在没有提前看别人的分析的情况下,我想我是看懂了一点点,大家不要见笑。基于OK3的源码啊。。
先来看个请求吧,普通的GET请求,服务器也是我自己搭建的(thinkPHP3.3环境,不要问我为什么会PHP,人都是鼻出来的!),来看代码:
Request.Builder builder = new Request.Builder().url(Api.GET_URL);final Request request = builder.build();OkHttpClient mOkHttpClient = new OkHttpClient() ; Call mCall = mOkHttpClient.newCall(request);mCall.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d(TAG , "onFailure : " + call ); Log.d(TAG , "onFailure exception : " + e) ; } @Override public void onResponse(Call call, Response response) throws IOException { Log.d(TAG , Thread.currentThread().getName() + "onResponse : " + call); Log.d(TAG, Thread.currentThread().getName() + " the response is " + response.body().string()) ; } });
先看Request.Builder吧,这个我先说一下吧,Request英文名对应请求,那么它肯定就是ok3封装的请求数据,Builder见得多了,装13一点就是Builder模式,写过android的对话框的,AlertDialog.Builder跟它一个样,顺便截个图,看看Request.Builder中到底有什么:
是的,它有HttpUrl,method,Header.Builder,RequestBody,tag。我们就简单理解一下吧,分别就是请求的Url,method,header 和 请求的body吧,这个先不看,简单了解一下,我想想也是,哈哈。
再来看这句代码吧:
OkHttpClient mOkHttpClient = new OkHttpClient() ; Call mCall = mOkHttpClient.newCall(request);
我们来看看newCall是干嘛用的:
它返回了一个newCall的东西,不管了,先提着裤子进去看看吧:
看不懂啊,先放着,接着看下面的代码:
mCall.enqueue(new callback);
此时的mCall就是我们已知的realCall,看看它的enqueue方法是做啥的:
信息量比较大,还是挑重点的吧,调用的了
client.dispatcher().enqueue(new AsyncCall(responseCallback));
这个client就是我们的OkHttpClient,那么这个dispatcher是什么呢?进去看看吧:
英文解释为异步的请求策略,看到下面的ExecutorService就是用线程池了,现在也不管最大并发数是多少了,自己进来看看就知道了。这个dispatcher应该就是OK3分发异步请求核心了,我们去看看它的enqueue方法了:
信息量也是比较大,我也就不展开扯了,判断正在执行的call数量和访问同一主机的数量,这些都不重要,重要的是看到了executorService().execute(call);多线程中学到了executorService.executte方法中,一定传入的是个Runnable对象,那么好吧,我们来看看这个AsyncCall对象是什么玩意吧:
看到了吧,的确是实现了Runnable接口的货,那个NamedRunnable是实现了Runnable接口,用意是要在Runnable在run时有个好用的名字,官方说为了避免每次设置名字而创建的:
看完了这,那就看看AsyncCall中的execute方法吧:
到现在为止,我们找到了在开始请求时,设置的Callback,在这里已经看到原型了,非常开心,非常高兴了,感觉马上就需要完成了啊。
我们的Response来自getResponseWithInterceptorChain()方法,进去看看了,看完了马上就可以睡觉了:
来看看这个图,为了这个方法我硬是傻了很长一段时间,设计了一个拦截器容器,装入了client.Interceptor,失败和重定向的Interceptor,请求头的Interceptor,还有缓存的Interceptor,连接用的Interceptor,还有netWork的Interceptor,最后一个连接服务器的Interceptor。
然后让我们的RealInterceptorChain进行process后获得Response,注意RealInterceptorChain中第四个参数是0,这个很有用。
现在进入RealInterceptorChain看看process方法:
前面一段是interceptor是合法性检测,不是我们的重点,重点是这个:
// Call the next interceptor in the chain. RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next);
最后直接interceptor.intercept(next)返回了Response,那好,我们来看看这个Interceptor接口是什么吧:
可以看到,Interceptor.intercept中传入的是一个Chain接口,重点还是看段代码,我又贴了一遍:
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, **index + 1**, request); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next);
光说图不是很明白,来张灵魂画工,估计能明白一点吧:
好了,看这张图我想你能明白我在说什么了,就是通过Chain的方式,将我们的Interceptor串联起来执行的,而且这个Chain名词也很形象,本身含义是链条的意思,的确啊,将所有的Interceptor连接起来,不就是链条么?这种模式我们称之为责任链模式,可能架构多了,很多东西都一样了吧,在web三个框架中Struct中,拦截器也是这么写的,使用责任链模式,非常的优雅和有效,值得我们学习啊。
至于到最后一个Interceptor.Intercept总该返回我们需要的Response吧,来看看最后一个Interceptor是什么了吧,不要忘记这张图啊:
最后一个是什么呢?是CallServerInterceptor,不说了,先进去看看intercept方法吧:
@Override public Response intercept(Chain chain) throws IOException { ... Response response = responseBuilder .request(request) .handshake(streamAllocation.connection().handshake()) .sentRequestAtMillis(sentRequestMillis) .receivedResponseAtMillis(System.currentTimeMillis()) .build(); int code = response.code(); if (forWebSocket && code == 101) { response = response.newBuilder() .body(Util.EMPTY_RESPONSE) .build(); } else { response = response.newBuilder() .body(httpCodec.openResponseBody(response)) .build(); } .... return response; }
代码都省略了啊,可以看出,最后一个使我们真正请求的Interceptor,并在这里完成了Response的组装,最后进行了返回,这个类里面涉及了很多http的知识,三次握手,返回码的知识等等,有时间再学习学习吧,这次写的还是有点多了。
通过简单的学习,我们了解一次OKHttp的请求,还是蛮复杂的,不能不说这样的设计真的需要水平,膜拜一下啊,当然了,很多地方也可能有错误或者分析不到位,希望大家指出啊,我也是只是写下自己的想法,大家共同进步吧。
- 其实你可以读懂OKHttp3的源码
- 程序员,其实你可以做的更好
- 其实你可以投诉
- 其实你可以更好
- 一本你肯定可以读懂的Java图书
- 一本你肯定可以读懂的Java图书II
- 拒绝百度,其实你可以!
- 其实你可以不需要心灵鸡汤
- Okhttp3的源码分析_小白看源码
- 一步步带你读懂 CoordinatorLayout 源码
- 中国男人,其实你可以很浪漫!
- 豆瓣 - 拒绝百度,其实你可以!
- 操作fd_set结构体的宏(其实,你也可以理解为函数,只要你喜欢)
- 读懂你的用户留存
- 读懂你的用户留存
- 其实计算机可以裸奔的
- 手把手教你读懂源码,View的加载流程详细剖析
- 手把手教你读懂源码,View的绘制流程详细剖析
- 学编程的一些感悟
- Java设计模式之命令模式
- 关于listview问题
- Go HSAIL and Other Language Standards Supported by GCC ( GCC 支持的Go HSAIL和其他语言标准 )
- linphone-获取sip:name@192.168.1.24中的name
- 其实你可以读懂OKHttp3的源码
- 关于在pdf文件中的中文字体显示
- AngularJS中的input指令
- 在安卓中使用Animation类实现基础动画效果
- ubuntu防火墙管理
- 剑指offer(java代码)——和为S的两个数字
- DevOps工具系列简介
- JAVA中静态代码块、构造方法、Super()父类与子类之间执行顺序
- spring mvc. 异步controller介绍