Android网络框架Okhttp3.0原理分析

主要成员

  • 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接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。

主要步骤

  1. 请求的封装:请求是由Okhttp发出,真正的请求都被封装了在了接口Call的实现类RealCall中。RealCall构造函数的逻辑是:赋值外部传入的OkHttpClient、Request与forWebSocket,并创建了重试与重定向拦截器RetryAndFollowUpInterceptor。

  2. 请求的发送:RealCall将请求分为同步异步两种,同步请求通过调用Call.exectute()方法直接返回当前请求的Response,异步请求调用Call.enqueue()方法将请求(AsyncCall)添加到请求队列中去,并通过回调(Callback)获取服务器返回的结果。

  3. 返回结果:不管是同步请求还是异步请求最后都会通过getResponseWithInterceptorChain()获取Response,只不过异步请求多了个线程调度,异步执行的过程。这个方法才是真正发起请求并处理请求的地方。

拦截器,采用了责任链模式

  1. 自定义的Interceptor,里面可以封装一些头文件和Log日志信息;
  2. RetryAndFollowUpInterceptor:重试和重定向的拦截器,重定向次数最大为20;
  3. BridgeInterceptor:作用就是在封装Request时将应用层数据结构转换成网络层调用的数据结构,然后再把请求返回的Response网络层数据结构转换成应用层数据结构;
  4. CacheInterceptor:负责读取缓存以及更新缓存。大致的思路为:首先检查缓存,如果存在,则根据缓存封装一个Request,带上 ETag,If-Modify-Since 标签,访问服务器,否则直接访问服务器,访问完以后,如果是304返回码,说明可以从缓存中拿数据,那我们就可以从缓存中拿数据,构建一个新的 Response 就行了。另一个操作就是存储数据,即根据服务端的返回码把可以缓存的数据保存在Cache里。只要能缓存,尽量缓存;
  5. ConnectInterceptor:负责与服务器建立连接;
  6. networkInterceptor:负责网络状态的拦截;
  7. CallServerInterceptor:负责从服务器读取响应的数据。

个人理解

  1. OkhttpClient实现了Call.Factory接口并复写了其中的方法newCall,newCall方法初始化了一个RealNewCall的实例,RealNewCall实现了Call接口并复写了其中有关网络请求的方法。
  2. 请求方式分为同步和异步,同步请求通过调用exectute()方法直接返回当前请求的Response,异步请求调用enqueue()方法将请求(AsyncCall)添加到请求队列中去,并通过回调(Callback)获取服务器返回的结果。
  3. 每一个Call都是一个请求,Dispatcher内部维护了一个线程池,Dispatcher将call 加入到双端队列中,然后通过线程池来执行call;
  4. 同步和异步请求最终都会执行getResponseWithInterceptorChain方法,内部通过Interceptor采用责任链模式分层实现缓存、透明压缩、网络 IO 等功能;最终将响应数据返回给用户。

注意点

  • 每种请求都设置了一个同步锁,确保每个call只能被执行一次不能重复执行。
  • OkHttpClient最好设置成单例模式
  • 同时请求不能超过并发数(64,可配置调度器调整);okhttp会使用共享主机,即地址相同的会共享socket;同一个host最多允许5条线程通知执行请求;
  • Okhttp3.0支持WebScoket,这样我们就可以非常方便的建立长连接了。在安全方面,OkHttp目前支持了TLS版本,以确保一个安全的Socket连接。

灵魂三连

  • Dispatcher是如何进行请求调度的?
  • 各个拦截器是如何实现的?
  • 连接与连接池是如何建立和维护的?

em.......有空再说吧......

猜你喜欢

转载自blog.csdn.net/S_Alics/article/details/99999976