Android 网络编程及常用框架使用

基础用法

  • 注意开启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来回调给主线程。

image.png

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并返回用来完成重连。
整体流程如下:


image.png

OkHttp链接复用机制
利用http的keepalive机制,OkHttp支持5个socket链接,链接由RealConnection封装,默认keepAlive为5分钟,用Deque<RealConnection>存储链接,通过put、get、等操作对Deque操作,另外判断链接中的计数对象StreamAllocation来进行自动回收链接。

Retrofit

Retrofit就是一个网络请求框架的封装,底层的网络请求默认使用的Okhttp,本身只是简化了用户网络请求的参数配置等,还能与Rxjava相结合,使用起来更加简洁方便。此外还能完成数据的转化(converterFactory),适配(callAdapterFactory),通过设计模式进行各种扩展。
涉及的设计模式:外观模式,构建者模式,工厂模式,代理模式,适配器模式,策略模式,观察者模式

本质过程

参考:
Android Retrofit 2.0 的详细 使用攻略(含实例讲解)

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

推荐阅读更多精彩内容

  • 1.Volley结构图 从上图可以看到Volley分为三个线程,分别是主线程、缓存调度线程、和网络调度线程,首先请...
    刘望舒阅读 699评论 1 6
  • Android 异步网络请求框架-Volley 1. 功能介绍 1.1. Volley Volley 是 Goog...
    Brian512阅读 3,887评论 2 40
  • 注:本文转自http://codekk.com/open-source-project-analysis/deta...
    Ten_Minutes阅读 1,290评论 1 16
  • 进入大学生活了,离开了家的怀抱,突然,进入了集体生活。 我比较害怕进入一个新的环境,或者说是忐忑,不安。怕自己长得...
    宅家妖怪阅读 157评论 0 0
  • 嘻嘻,突然想整合一下精读营时的打开内容,这是一篇幻想内容,自娱自乐。 微习惯养成记1 "今天真的倒霉透了,真想拍屁...
    一点小贤阅读 738评论 2 6