OkHttp源码简单分析

核心类:OkHttpClient Call Request Response Dispatcher Interceptor

Request、Response比较好理解,请求数据和返回数据

OkHttpClient 使用new OkHttpClient()或new OkHttpClient.Builder().build()创建OkHttpClient实例,来进行网络请求。默认会创建ConnectionPool、Dispatcher、SocketFactory等。

Dispatcher 一个OkHttpClient的所有请求队列、分发

Call 接口,一次具体请求的封装,会再调用Dispatcher进行处理。

Transmitter Exchange

网络请求流程

先看下流程图

一、execute()同步请求 创建RealCall对象 流程:(没有创建新的线程)

  1. 调用newCall创建Call对象,具体创建RealCall对象,并创建Transmitter对象。
  2. 调用Call对象的execute()方法。
  3. 调用Dispatcher的execute()方法,将RealCall添加到Dispatcher中的runningSyncCalls队列
  4. 处理所有拦截器,包括用户添加的,还有OkHttp自己内部创建的。
  5. gerResponseWithInterceptorChain()网络请求和返回,由拦截器封装和处理。

    (1) RetryAndFollowUpInterceptor 重试和重定向拦截器
        调用Transmitter.prepareToConnect()方法,创建ExchangeFinder对象。
    (2) BridgeInterceptor 桥接拦截器,负责请求构建和响应结果封装。
    (3) CacheInterceptor 缓存拦截器,负责缓存网络数据
    (4) ConnectInterceptor 连接拦截器,负责socket的IO操作,使用的是Okio封装的类。(使用Exchange类)
        调用ExchangeFinder.find()创建RealConnection对象,并创建Socket连接。返回创建Exchange和ExchangeCodec对象。
        ExchangeCodec是接口,具体实现是Http1ExchangeCodec和Http2ExchangeCodec.
    (5) CallServerInterceptor 访问服务拦截器,最后一个拦截器。向服务器发送Request请求,即将请求header和body写入socket,然后读取响应的header和body,创建返回需要的Response对象。(使用Exchange类)
        通过Exchange发送Request和获取Response。
复制代码
  1. 调用Dispatcher中的finished()方法

     (1) 从runningSyncCalls队列中移除。
     (2) 调用promoteAndExecute()方法,处理readyAsyncCalls队列中的网络请求。
    复制代码

二、enqueue()异步请求 创建AsyncCall对象,Callback异步请求的回调。

流程:

  1. 调用newCall创建Call对象,具体创建RealCall对象,并创建Transmitter对象。
  2. 调用Call对象的enqueue方法,创建AsyncCall对象,AsyncCall继承NamedRunnable,实现Runnable,即是个线程类。
  3. 调用Dispatcher的enqueue()方法,将AsyncCall添加到Dispatcher中的readyAsyncCalls队列。
  4. 调用promoteAndExecute()方法,从readyAsyncCalls获取AsyncCall对象,利用线程池,执行当前AsyncCall线程。
  5. NamedRunnable的线程run方法,会再调用子类的execute()方法。即AsyncCall的execute()方法。
  6. AsyncCall的execute()方法会调用gerResponseWithInterceptorChain(),处理拦截器。获取返回Response对象
  7. 将返回的Response对象,返回给Callback。
  8. 最后调用Dispatcher中的finished()方法

OkHttp扩展知识

  1. 请求任务缓存使用了Dequeue Queue Dequeue ArrayQueue

Queue 也是 Java 集合框架中定义的一种接口,直接继承自 Collection 接口。Queue 接口还定义一组针对队列的特殊操作。

Deque 接口继承自 Queue接口,但 Deque 支持同时从两端添加或移除元素,因此又被成为双端队列。鉴于此,Deque 接口的实现可以被当作 FIFO队列使用,也可以当作LIFO队列(栈)来使用。官方也是推荐使用 Deque 的实现来替代 Stack。

ArrayDeque 是 Deque接口的一种具体实现,维护一个数组和首尾位置。如果数组容量已满,则会创建新的2倍容量的数组,并赋值。

/**
 * The array in which the elements of the deque are stored.
 * The capacity of the deque is the length of this array, which is
 * always a power of two. The array is never allowed to become
 * full, except transiently within an addX method where it is
 * resized (see doubleCapacity) immediately upon becoming full,
 * thus avoiding head and tail wrapping around to equal each
 * other.  We also guarantee that all array cells not holding
 * deque elements are always null.
 */
transient Object[] elements; // non-private to simplify nested class access

/**
 * The index of the element at the head of the deque (which is the
 * element that would be removed by remove() or pop()); or an
 * arbitrary number equal to tail if the deque is empty.
 */
transient int head;//数组首元素位置

/**
 * The index at which the next element would be added to the tail
 * of the deque (via addLast(E), add(E), or push(E)).
 */
transient int tail;//数组尾元素的下个位置
复制代码

在 ArrayDeque 中数组是当作环形来使用的,在容量保证为 2^n 的情况下,仅仅通过位与操作就可以完成环形索引的计算,而不需要进行边界的判断,在实现上更为高效。

环形结构:

位与运算:新位置和(elements.length - 1)做与运算

先看添加头:

head的新位置一定是head-1,如果得到的结果为-1,就要挪到右侧,也就是物理数组的最后一个位置length-1。

if (head-1 >= 0) {
    head=head-1;
} else {
    head=elements.length -1;
}
elements[head]=e;
复制代码

而ArrayDeque使用了性能更好的位与运算

elements[head = (head - 1) & (elements.length - 1)] = e;
复制代码

相比ArrayList,我们可以看到ArrayDeque大量减少了System.arrayCopy的使用。

  1. 线程池
public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
复制代码

SynchronousQueue 阻塞队列 BlockingQueue 同步锁 ReentrantLock

你可能感兴趣的:(OkHttp源码简单分析)