基础用法
注意开启connection时机
getInputStream, getOutputStream会隐式地创建链接,不过显式调用也无妨,因为当已经建立链接,重复connect请求会被忽略。断开connect请求的时机
当connection的模式是keep-alive时候,调用如InputStream.close()不会将socket链接关闭,socket可以被复用,调用connection.disconnect才能关闭链接。
HttpURLConnection 基础用法上传到了github
https://github.com/LeeFranz/Android-Network
用法详解在以下文章
https://www.jianshu.com/p/cfefdc4e062e
Volley原理
1、构建requestQueue,构建时候根据当前sdk版本,大于9使用基于HttpURLconnection的HurlStack,否则使用基于HttpClient的HttpClientStack,创建好queue后调用它的start方法,其中会启动启动一个缓存调度线程和四个网络调度线程,即CacheDispatcher.start(),newtworkDispatcher.start(),这样就有5个线程等待处理网络请求。
2、记下来创建各种request,并调用RequestQueue的add()方法。如果不能缓存,则将请求添加到网络请求队列networkQueue中,否则,如果之前有相同的请求而且还没有返回结果的,就将此请求加入waitingrequest队列,之前没有相同请求的话就加入缓存队列cacheQueue。网络调度线程或者缓存调度线程中发现各自队列中新的请求时候就会开始执行。
3.1看CacheDispatcher调度线程的run方法。先从缓存队列中获取一个请求,如果请求被取消了,就将其停止。然后查看缓存中是否有该请求的响应,如果有且没过期即hit就对数据进行解析并回调给主线程;如果缓存响应为空即miss,就将请求加入网络队列。
3.2 看NetworkDispatcher的网络调度线程。类似地,从网络请求队列中取得request,如果已经取消了就将其终结,否则就去请求网络并将其响应回调给主线程。请求网络时候调用this.mNetwork.performRequest(request),这个mNetWork是个接口,其实现类是BasicNetWork。
3.2.1调用httpStack.performRequest方法发起请求,这个httpStack之前已经 提到是基于HttPClient或者HTTPURLConnection实现的 ,根据不同的状态码来返回不同的netWorkResponse
3.2.2 请求网络后会将结果存在缓存中,并调用Delivery.postResponse来回调给主线程。
demo地址:https://github.com/LeeFranz/Android-Network/tree/master/Internet_2_volley
OkHttp原理
1、OkHttpClient.newCall(request)进行enqueue操作的时候,实际会调用RealCall.enqueue。最终请求是由client.dispatcher.enqueue完成的。最大并发请求数
2、通过dispatcher维护一个线程池,就绪的异步请求队列readyAsyncCalls,正在运行的异步请求队列 runningAsyncCalls, 正在运行的同步请求队列runningsyncCalls。如果异步请求队列数量小于64并且正在运行的请求主机数量小于5,就把请求加入到runningAsyncCalls中并在线程池中执行,否则就加入到readyAsyncCalls中进行缓存等待。如果是execute操作就会使用同步请求队列。
3、client.dispatcher.enqueue传入的参数是AsyncCall,是RealCall的内部类,它会被传入线程池执行请求,具体方法也是execute,实现操作包括通过getResponseWithInterceptChain返回response,如果请求成功就通过Callback.onResponse回调。最终都会执行finished方法——将当前请求从runningAsyncCalls移除后执行promoteCalls方法——从readyAsyncCalls取出下一个请求,加入runningAsyncCalls。
3.1 看getResponseWithInterceptorChain方法,通过遍历拦截器链。拦截器是一种能够监控、重写、重试调用的机制,通常用其添加、移除、转换请求和响应的头部信息,比如将域名替换为IP地址,在请求头中添加host属性。依次取出拦截器,并在interceptor.intercept()处阻塞,等待下一个拦截器调用返回,这样当所有拦截器都处理完后,就通过方法末尾的getResponse方法请求网络,主要操作是调用HttpEngine的sendRequest和readRequest方法。
3.2 HttpEngine的sendrequest方法,先读取缓存目录中曾经请求过的信息,这里的缓存基于map,key是请求中url的md5,value是在文件中查询到的缓存,页面置换基于LRU算法。然后判断networkRequest和cacheResponse,两者都为空,即不进行网络请求或缓存不存在或过期,则返回504错误,如果不进行网络请求且缓存可用,那么直接返回缓存,否则在请求网络。在HttpEngine的readResponse中,先读取网络响应,如果有缓存并且当前缓存可用,则用缓存的数据并更新缓存,否则就用网络请求返回的数据。
回到getResponse中,当发生IOException或者RouteException时候都会执行HttpEngine的recover方法,重新创建了HttpEngine并返回用来完成重连。
整体流程如下:
OkHttp链接复用机制
利用http的keepalive机制,OkHttp支持5个socket链接,链接由RealConnection封装,默认keepAlive为5分钟,用Deque<RealConnection>存储链接,通过put、get、等操作对Deque操作,另外判断链接中的计数对象StreamAllocation来进行自动回收链接。
Retrofit
Retrofit就是一个网络请求框架的封装,底层的网络请求默认使用的Okhttp,本身只是简化了用户网络请求的参数配置等,还能与Rxjava相结合,使用起来更加简洁方便。此外还能完成数据的转化(converterFactory),适配(callAdapterFactory),通过设计模式进行各种扩展。
涉及的设计模式:外观模式,构建者模式,工厂模式,代理模式,适配器模式,策略模式,观察者模式