写在前面
- OKHTTP,HttpURLConnection:底层是java的Socket,要在子线程调用, 通过handler发送结果到主线程
- NoHttp:Android4.4以后也是使用okHttp做底层的。 文件下载, 断点续传, 304缓存, 302/303传参数,
传文件, 请求头, 多文件上传, 大文件上传, Cookie自动管理 Volley:底层是HttpClient;Android 6.0已经删除了,所以看不了6.0源码。没有NoHttp那么多功能,要自己去实现
OkHttp和HttpURLConnection一样, 是面向java的, 因为它的最底层走到了java的Socket,利用向Socket写入特定的Http协议数据包,使用时要在子线程调用, 通过handler发送结果到主线程
NoHttp和Volley不是做socket层的东西. 直接在主线程就可以调用, 拿到结果后直接更新UI, 不需要用handler去发送
OkHttp是一个高效的Http客户端,有如下的特点:
支持HTTP2/SPDY黑科技,共享同一个Socket来处理同一个服务器的所有请求
socket自动选择最好路线,并支持自动重连
拥有自动维护的socket连接池,减少握手次数
拥有队列线程池,轻松写并发
拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
基于Headers的缓存策略,减少重复的网络请求
我们从以下几个方面讲解okHttp
- okHttp请求的整个流程
优点
拥有线程池,且采用阻塞队列SynchronousQueue实现高并发,高效率。
OkHttp采用Dispatcher技术,类似于Nginx,与线程池配合实现了高并发,低阻塞的运行
OkHttp最出彩的地方就是在try/finally中调用了finished函数,可以主动控制缓存队列的移动,而不是采用锁,极大减少了编码复杂性,也避免了死锁发生。
Interceptors拦截器是okhttp中强大的流程装置,修改请求,修改结果,甚至是对用户透明的GZIP压缩
Socket连接池采用引用计数法,及时回收空闲和被释放socket,从而保证多个健康的keep-alive连接。
工作流程
当我们用OkHttpClient.newCall(request)进行execute/enenqueue时,实际是将请求Call放到了Dispatcher中,okhttp使用Dispatcher进行线程分发,它有两种方法,一个是普通的同步单线程;另一种是使用了队列进行并发任务的分发(Dispatch)与回调,但是他们最终都会执行getResponseWithInterceptorChain()方法,该方法产生了HTTP返回结果的,但是在这中间进行了一系列的Interceptors链条拦截处理,最后当该请求执行完了后还会通知dispather自己已经执行完了,调用dispather.finished()将其从runningCalls移除,并检查缓存队列中是否有请求,如果没有等待,有则将缓存队列中队尾请求移除,加入runningCalls,并且在线程中池中执行该请求
在上述过程中我们就体现了上述说的四个优点
异步处理请求时使用了线程池和Dispather分发技术。
在返回结果时进行了拦截处理,可以把实际的网络请求、缓存、透明压缩等功能统一起来。
当请求执行完后会进入finally执行finished函数。
线程池
首先是Volley中的工作线程是自己维护的,那么就有可能存在线程由于异常退出之后,没有下一个工作线程补充的风险(线程池可以弥补这个缺陷),那okhtyp是怎样避免volley的这个缺陷呢?首先是okhttp是有线程池的,其次这个线程池采用了SynchronousQueue这种阻塞队列。(SynchronousQueu