主要成员
- OkHttpClient:是OkHttp框架的客户端,用户使用OkHttp进行各种设置,发起各种网络请求都是通过OkHttpClient完成的。每个OkHttpClient内部都维护了属于自己的任务队列,连接池,Cache,拦截器等,所以在使用OkHttp作为网络框架时应该全局共享一个OkHttpClient实例。
- Call:Call是描述一个实际的访问请求,用户的每一个网络请求都是一个Call实例。Call本身只是一个接口,定义了Call的接口方法,实际执行过程中,OkHttp会为每一个请求创建一个RealCall,每一个RealCall内部有一个AsyncCall,AsyncCall是RealCall的一个内部类并且继承NamedRunnable,NamedRunnable实现了Runnable接口并且是一个抽象类,有一个抽象方法
execute()
,这个方法在run()
中被调用。这也就意味着NamedRunnable是一个线程,并且其子类应该实现execute方法。AsyncCall继承NamedRunnable,实现了抽象方法execute()
,所以每一个Call就是一个线程,而执行Call的过程就是执行其execute()
方法的过程。 - Dispatcher(调度器):是OkHttp的任务队列,其内部维护了一个线程池,当接收到一个Call时,Dispatcher负责在线程池中找到空闲的线程并执行其execute方法。
-
Inteceptor:拦截器是一种强大的机制,可以监视、重写和重试调用。拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。
主要步骤
-
请求的封装:请求是由Okhttp发出,真正的请求都被封装了在了接口Call的实现类RealCall中。RealCall构造函数的逻辑是:赋值外部传入的OkHttpClient、Request与forWebSocket,并创建了重试与重定向拦截器RetryAndFollowUpInterceptor。
-
请求的发送:RealCall将请求分为同步和异步两种,同步请求通过调用Call.exectute()方法直接返回当前请求的Response,异步请求调用Call.enqueue()方法将请求(AsyncCall)添加到请求队列中去,并通过回调(Callback)获取服务器返回的结果。
-
返回结果:不管是同步请求还是异步请求最后都会通过getResponseWithInterceptorChain()获取Response,只不过异步请求多了个线程调度,异步执行的过程。这个方法才是真正发起请求并处理请求的地方。
拦截器,采用了责任链模式
- 自定义的Interceptor,里面可以封装一些头文件和Log日志信息;
- RetryAndFollowUpInterceptor:重试和重定向的拦截器,重定向次数最大为20;
- BridgeInterceptor:作用就是在封装Request时将应用层数据结构转换成网络层调用的数据结构,然后再把请求返回的Response网络层数据结构转换成应用层数据结构;
- CacheInterceptor:负责读取缓存以及更新缓存。大致的思路为:首先检查缓存,如果存在,则根据缓存封装一个Request,带上 ETag,If-Modify-Since 标签,访问服务器,否则直接访问服务器,访问完以后,如果是304返回码,说明可以从缓存中拿数据,那我们就可以从缓存中拿数据,构建一个新的 Response 就行了。另一个操作就是存储数据,即根据服务端的返回码把可以缓存的数据保存在Cache里。只要能缓存,尽量缓存;
- ConnectInterceptor:负责与服务器建立连接;
- networkInterceptor:负责网络状态的拦截;
- CallServerInterceptor:负责从服务器读取响应的数据。
个人理解
- OkhttpClient实现了Call.Factory接口并复写了其中的方法newCall,newCall方法初始化了一个RealNewCall的实例,RealNewCall实现了Call接口并复写了其中有关网络请求的方法。
- 请求方式分为同步和异步,同步请求通过调用exectute()方法直接返回当前请求的Response,异步请求调用enqueue()方法将请求(AsyncCall)添加到请求队列中去,并通过回调(Callback)获取服务器返回的结果。
- 每一个Call都是一个请求,Dispatcher内部维护了一个线程池,Dispatcher将call 加入到双端队列中,然后通过线程池来执行call;
- 同步和异步请求最终都会执行getResponseWithInterceptorChain方法,内部通过Interceptor采用责任链模式分层实现缓存、透明压缩、网络 IO 等功能;最终将响应数据返回给用户。
注意点
- 每种请求都设置了一个同步锁,确保每个call只能被执行一次不能重复执行。
- OkHttpClient最好设置成单例模式
- 同时请求不能超过并发数(64,可配置调度器调整);okhttp会使用共享主机,即地址相同的会共享socket;同一个host最多允许5条线程通知执行请求;
- Okhttp3.0支持WebScoket,这样我们就可以非常方便的建立长连接了。在安全方面,OkHttp目前支持了TLS版本,以确保一个安全的Socket连接。
灵魂三连
- Dispatcher是如何进行请求调度的?
- 各个拦截器是如何实现的?
- 连接与连接池是如何建立和维护的?
em.......有空再说吧......