OKHttp 同步异步请求步骤 以及拦截器笔记

http 1.0 和http1.1的区别

http 1.0 如果一个请求发到服务器 每次的传输 都会有 三次握手 四次挥手

客户端建立连接 发送请求到服务器 服务器发送消息给客户端  连接成功

客户端收到服务器发过来的消息 客户端发送数据包给服务器 

互相通知 两次断开 最后一次服务器断开发送给客户端

1.1 可以进行长链接  可以不停的交互 直到不需要连接 进行四次挥手 断开连接

htpp 

第一行: 请求行

请求行下面的: 请求的属性集  Header请求头  以及请求参数

请求状态码

请求时间 字符类型

请求返回的具体内容

1.为什么选择okHttp 而不是其他框架

OKHttp基于socket通讯,它更倾向于底层,会对http协议进行完全的封装 

第一点:谷歌官方在6.0以后在android sdk已经移除了httpClient,加入我们okHttp.

第二点:okHttp支持SPDY(是谷歌开发的基于TCP的应用层协议,用于最小化网络延迟,提升网络速度,优化用户的网络使用体验. SPDY并不是一种替代http的协议,只是对http的一种增强.)允许连接在一主机的所有请求分享一个socket.如果SPDY不可用.会使用连接池来减少请求延迟.利用响应缓存来避免重复的网络请求.即便是网络出现问题时,okhttp依然起作用.它将从常见的链接问题当中回复.如果你的服务器有多个IP地址,当地一个失败时,okhttp会自动尝试连接其他的地址.这对于IPV4和IPV6以及寄宿在多个数据中心的服务而言,是非常有必要的,所以okhttp的稳定性可以说是非常棒的.


2.为什么retrofit能请求为什么还要+okhttp

因为retrofit只是一个网络框架的封装,他不负责请求,内部源码请求还是okhttp。他是把接口方法动态代理转换成ok能读懂的请求的,你要是想配置拦截器,超时等,你还得引入okhttp自己配置啊


OKHttp 流程详解

1.new OKhttpClient()  初始化一个OKhttpClient

2.初始化一个Request.Builder  这个里面 可以.url .addHeader(name,value)

 .build();等一些请求参数 设置请求类型 默认是GET请求类型

3.创建一个Call  call=okhttpClient.newCall(request) 

call.execute(new Callback) 同步请求

Call.enqueue(new Callback) 异步请求

在new Call中  会返回一个RealCall.newRealCall的方法  这里进行相关操作 

Call call= return RealCall.newRealCall(this, request, false /* for web socket */);

在执行call.execute或者call.enqueue的时候跳转到realcall 

call.execute

//分发同步或异步  在这个exexuted()中吧穿进去的RealCall添加进一个runingSyncCall队列中去

然后这里这个retrun getResponseWithInterceptorChain(); 这句代码执行之后返回了一个 Response 就是我们发送数据,服务器给我们的相应数据 在这个getResponseWithInterceptorChain中进行了一些拦截器的操作 

这样同步请求会直接等待服务器返回的一个Response 我们就回对这个Response进行处理

 

Response

 

异步请求

enqueue()异步请求也是在RealCall中实现

在RealCall中 有个pulic void enequeue(Callback responeCallback)方法

这里会用client.dispatcher.enqueue(new AsynCall(respnseCallback))

call.enqueue

client.dispatcher().enqueue这个方法也是分发器中实现的

client.dispatcher().enqueu


在分发器中 吧穿进去的new AsyncCall(respnseCallback)子线程添加到了一个队列 readyAsynsCalls中去 然后执行promoteAndExecute()方法

promoteAndExecute();这个方法中asyncCall.executeOn(executorService());

进行了一个线程池的创建操作

 

promoteAndExecute()
线程池创建

client.dispatcher().enqueue(new AsyncCall(responseCallback));

然后回到之前 AsyncCall() 这个继承了 NamedRunnable这个类

这个类是个抽象类,里面有写到 extctue抽象方法 那么AsyncCall这里面就会执行 extctue 

 

NamedRunnable

这里就是在RealCall中的AsyncCall类里面重写的void execute方法

@Override protected void execute() {

在这个方法里面我们得到了发起请求后的Response 

 Response response = getResponseWithInterceptorChain();

  signalledCallback =true;

   responseCallback.onResponse(RealCall.this, response)


@Override protected void execute()


然后在请求外面的CallBack里面onResponse 进行相应的操作

总结:

1)同步和异步都是通过Dispatch这个分发器来分发的。

2)异步操作比同步操作多了创建线程池的操作,开启了子线程。

3)同步和异步最后都走到了getResponseWithInterceptorChain这个方法。


OKhttp拦截器的使用

拦截器分为内部拦截器 和外部拦截器

内部拦截器有5个

外部拦截器就是自己定义的拦截器

还可以分为应用拦截器和网络拦截器 这两个拦截器都需要实现intercept接口

应用拦截器:关注的是发起请求,不能拦截发起请求到请求成功后返回数据的中间的这段时间  也就是说 在发起请求之前 这个拦截器是生效的 很简单的一个例子 添加一个TokenHeaderIntercpter  定义个token  吧这个token添加到 builder中的header里面去

OkHttpClient.Builder okHttpClient2 = new OkHttpClient().newBuilder();

 okHttpClient2.addInterceptor(new TokenHeaderInterceptor());

 public class TokenHeaderInterceptor implements Interceptor {

        @Override

        public Response intercept(Chain chain) throws IOException {

            // get token

            String token = "123456";

            Request originalRequest = chain.request();

            // get new request, add request header

            Request updateRequest = originalRequest.newBuilder()

                    .header("token", token)

                    .build();

            return chain.proceed(updateRequest);

        }

    }

网络拦截器:是发起请求和请求后获取的数据中间这样一个过程 这这个过程中起到作用

前者是.addIntercpter  它是addNetWorkIntercepter 从名字就能看出来 是不一样的拦截器

应用拦截器和网络拦截器区别在于 网络拦截器可以重定向

在getResponseWithIntercepterChain方法里面 可以看到有一个list<Intercepter>方法

会吧okhttpclient中所有的intercepttian添加到这个list里面去可以看到在添加完自定义intercept之后 还会添加五个拦截器


RetryAndFollowUpInterceptor //重试和失败重定向拦截器,会创建StreamAllocation对象,用来传递给后面的拦截器

BridgeInterceptor  桥接和适配拦截器 

CacheInterceptor  缓存拦截器

BridgeInterceptor和CacheInterceptor用于补充用户创建请求中缺少的一些必须请求头,和处理缓存功能

ConnectInterceptor 连接拦截器,建立可用的连接,是CallServerIntercpter的基础

CallServerInterceptor 负责将我们的请求写进网络流中,并且我们会从网络Io流当中读取服务器返回给我们的客户端的数据

RetryAndFollowUpIntercepto

主要执行工作

1.创建一个StreamAllocation对象

2.调用RealIntercepterChainrealChain.proceed(requesr,streamAllocation,null.null) 通过chain对象调用下一个拦截器 BirgeIntercepter

3.从下一个拦截器接受传递过来的Response 根据异常和相应结果判断是否需要重连

4.处理完成之后将Response返回给上一个拦截器  就是getResponseWithIntercepterChian这个拦截器   

BirgeIntercepter拦截器 

这个拦截器 负责设置内容长度,编码方式,设置gzip压缩,添加请求头,cookie等相关功能

桥接拦截器是链接客户端和网络代码的桥梁, 这个拦截器会根据用户请求创建真正的网络请求 NetWork Request

主要功能

1、负责将用户构建的一个Request请求转换成一个能够进行网络访问的请求

2. 将这个符合网络请求的Response转化为用户可以使用的Response

CacheIntercepter拦截器

缓存拦截器, 为什么要使用缓存?

一个优点就是让客户端下一次进行网络请求的时候能够节省更多的时间,更快的展示数据

如果有网络请求数据缓存, 客户端在没有网络的情况下,会直接返回缓存结果,避免很多尴尬现象

当CacheIntercept拦截到请求之后会调用cache类中的put方法 cache类 实现了internalCache接口,此接口定义了真删改查等方法

Http的缓存的工作是通过CacheIntercept拦截器完成的

如果当前未使用网络,并且网络不可用的时候,通过构建者模式会串讲一个Response相应抛出504错误,告诉客户端 网络不可用

如果有缓存,但是不能请求网 会直接返回缓存结果

这是在进行网络请求之前所做的事情, 当网络请求完成,得到下一个拦截器返回的Response之后根据Response的响应码是否是HTTP_NOT_MODIFIED=304(未改变) 那就会缓存中读取数据

这个拦截器负责打开服务之间的TCP连接,正式开启okhttp的网络请求

ConnectIntercepter执行完请求之后接着做的就是读取服务器相应的数据,构建resonse.builder对象

主要做了两个工作

1.调用HttpCodec的readResponseHeaders方法读取服务器相应数据,构建Response.Builderd对象

2.通过ResponseBuilder对象来创建Response对象并返回,主要是调动Http1Codec对象的openResponseBody方法,此方法讲Scoket的输入流inputStream对象交给Oklo的Source对象,然后方封装成RealResponseBody作为Response的body

CallServerIntercepter拦截器 

主要做了如下工作

1.获取HttpCodec对象 对Http协议的http请求进行处理

2.发送http请求数据,构建Response.Builder对象,然后构建Response并返回

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