okhttp网络框架源码解析三okhttp网络框架源码解析同步请求的执行流程及源码分析

241 篇文章 5 订阅

一、okhttp同步请求和源码分析

1、okhttpclient对象的创建

不管同步请求也好,异步请求也好,都需要创建OkHttpClient,然后创建Request,然后调用okhttp的newCall()方法,创建实际的okhttp请求call对象。对于同步请求会调用OK HTTP的execute()方法,对于异步请求会调用enqueue()这个方法,这只是外部调用方法的简单区别,其实内部的实现是由很大的区别的。

第一步创建OkHttpClient,用到了参数,涉及到了内部类Builder。

Builder的构造方法。

dispatcher对象之所以重要是因为它是okhttp请求的分发器,由它决定okhttp请求是直接处理还是执行等待,对于同步请求,它其实没有做太多操作,只是把它的同步请求放到队列当中去执行。

connectionPool对象,其实是一个连接池,也是okhttp请求当中一个很终于的概念。怎么来理解这个连接池呢?客户端和服务器直接的连接,我们把它抽象为一个connection,而每一个连接都把它放在connectionpool连接池当中,由它进行统一的管理。当请求的url相同的时候,就可以选择复用,这就是作用之一。作用之二就是,connectionppool这个类实现了哪些网络连接,它可以保持打开状态,哪一些是可以用来复用的这些策略的设置,也是通过connectionpool这个连接池进行管理的。构造方法中的这些参数,在后面都会用到,很明显,这是build构造模式,也就是用Builder对象封装okhttp初始化所需要的参数,然后传递Builder对象到okhttpclient构造方法里,完成整个对象的初始化。其实,当创建一个对象,需要很多参数的时候,可以使用build这个模式,它是一种很好的解决办法。在okhttp当中,或者其它开源框架当中,或者在平常的业务开发当中,也经常会用到build创建模式。这样就完成了okhttpclient这个客户端类的创建。

 

2、okhttp请求报文对象Request对象的创建

Request这个对象的创建也是build模式来创建,通过链式调用,给request指定url或者头部以及方法等等。

rquest内部类Builder的构造方法,这个构造方法非常简单,第一行指定了请求方法为“get”,它是默认的,然后创建了一个Headers的内部类Builder对象,用来保存header的一些信息,保存头部信息。

 

request的build()方法

 

它的build()方法里面直接创建了一个Request对象。然后把当前的builder对象传递过去。其实它的意思很明显,就是把刚才配置的头部、url等信息赋值给rquest这个对象,

 

request的构造方法就是为请求指定url、头部、请求方法等等,这样就完成了okhttp请求的前两步。

3、创建call对象

call对象是通过client的newCall()方法实现的

由于call是一个接口,所以它的实现都是在它的实现类RealCall中实现的。

 

realCall中的实现方式。

首先创建了一个它的实现类RealCall对象,然后赋值了一个eventListener,然后就返回了。但是,它到底做了哪些工作呢?还是到realcall的构造方法里面看一下。

 

 

 

 

realcall的构造方法:

realcall其实持有了okhttpclient和request这两个对象,同时它还赋值了一个重定向拦截器。不管是同步请求还是异步请求,都是调用的client的newCall()这个方法来进行创建的,然后可以通过创建好的call对象来进行相应的操作

 

4、通过执行call的execute()方法来完成同步请求

 

call是一个接口,具体的实现在realcall中

 

这是realcall中的execute实现

首先,在同步代码块中判断execute这个标志位是否为true,它的意思是,同一个okhttp请求,只能执行一次,没有执行过,就会把这个标志位置为true,如果执行过,则抛出异常。

接下来会通过captureCallStackTrace()捕捉一些http请求的堆栈信息。

接下来开启了一个监听事件,每当call调用execute()或者enqueue()方法的时候就会开启这个listener。

最关心的还是这几个方法,首先,会调用client的dispatcher()方法,该方法做法很简单,只是返回请求的分发器

 

 

client.dispatcher().execute(this)的execute()方法比较重要

 

同步的请求其实就是把请求添加到队列当中,这就完成了这个操作

 

同步请求队runningSyncCalls列其实是在dispatcher这个类中定义的。它其实还定义了其它两个队列,一个是异步就绪队列readyAsyncCalls,一个是异步的执行队列runningAsyncCalls

 

在完成executed()方法之后,会调用getResponseWithInterceptorChain()方法获取response对象。这个其实是一个拦截器链的方法,在这个内部会依次调用拦截器来完成相应方法的处理。在finnally中由一个很重要很微妙的机制,client.dispatcher().finished(this)的finished()方法,它会主动回收它的某些同步请求。

 

 

 

 

它还调用了另外一个finished()方法

 

在finished()方法中,把我们正在执行的同步请求传了进来。199行,它首先回去同步请求队列中移除正在执行的请求,如果不能移除,就会抛出异常。注意这里移除的是同步请求。上面finished方法第三个参数是false,所以传入进来的promoteCalls是false,所以走不到下面方法的promoteCalls()这个方法里。但是,在异步的时候会走到。然后会调用runningCallsCount来计算正在运行的请求。最后判断正在执行的请求个数,如果为0,则表示没有正在执行的请求了,同时,如果idleCallback不为null的化,就可以调用它的run()方法。至此,所有同步请的执行流程就分析完了。

 

 

 

runningCallsCount()方法非常简单,就是返回了正在执行的同步请求和异步请求的数量总和

 

 

在同步请求中,dispatcher分发器所做的工作非常简单,主要是保存同步请求,移除同步请求,异步请求中,dispatcher所作的工作就更多了。

注:

其实dispatcher就是维持call请求发送给它的一些状态,同时,它也维护了一个线程池,用于执行网络请求。call通过dispatcher将它的请求推到队列当中进行操作。

5、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值