Android OkHttp3源码详解——整体框架

一 前言

之前写过一遍文章Android OkHttp3简介和使用详解,当时说要写 OkHttp3源码详解,由于各种原因,源码详解来的有点晚,下面我们先来来看一下流程图。

这里写图片描述

二 源码整体架构

这里写图片描述
上图是OkHttp3的整体框架,大致可以分为以下几层:

  • Interface——接口层:接收用户的网络访问请求(同步请求/异步请求),发起实际的网络访问
  • Protocol——协议层:处理协议逻辑
  • Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
  • Cache——缓存层:管理本地缓存
  • I/O——I/O层:实际数据读写实现
  • Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑

2.1 Interface——接口层

接口层接收用户的网络访问请求(同步请求/异步请求),发起实际的网络访问

  1. OkHttpClient:是OkHttp框架的客户端,更确切的说是一个用户面板。用户使用OkHttp进行各种设置,发起各种网络请求都是通过OkHttpClient完成的。每个OkHttpClient内部都维护了属于自己的任务队列,连接池,Cache,拦截器等,所以在使用OkHttp作为网络框架时应该全局共享一个OkHttpClient实例。

  2. Call:Call是描述一个实际的访问请求,用户的每一个网络请求都是一个Call实例。Call本身只是一个接口,定义了Call的接口方法,实际执行过程中,OkHttp会为每一个请求创建一个RealCall,每一个RealCall内部有一个AsyncCall,AsyncCall是RealCall的一个内部类并且继承NamedRunnable,那么首先看NamedRunnable类是什么样的,如下:

public abstract class NamedRunnable implements Runnable {
  ......

  @Override 
  public final void run() {
   ......
    try {
      execute();
    }
    ......
  }

  protected abstract void execute();
}

NamedRunnable实现了Runnable接口并且是一个抽象类,有一个抽象方法execute(),这个方法在run()中被调用。这也就意味着NamedRunnable是一个线程,并且其子类应该实现execute方法。下面再看AsyncCall的实现:

final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }

    ......
final class RealCall implements Call {
  @Override protected void execute() {
  boolean signalledCallback = false;
  try {
     Response response = getResponseWithInterceptorChain();
  if (retryAndFollowUpInterceptor.isCanceled()) {
     signalledCallback = true;
     responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
  } else {
    signalledCallback = true;
    responseCallback.onResponse(RealCall.this, response);
  }
 } catch (IOException e) {
  ......
  responseCallback.onFailure(RealCall.this, e);

} finally {
    client.dispatcher().finished(this);
  }
}

AsyncCall继承NamedRunnable,实现了抽象方法execute(),所以每一个Call就是一个线程,而执行Call的过程就是执行其execute()方法的过程。

3.Dispatcher(调度器)是OkHttp的任务队列,其内部维护了一个线程池,当有接收到一个Call时,Dispatcher负责在线程池中找到空闲的线程并执行其execute方法。

2.2 Protocol——协议层

Protocol层负责处理协议逻辑,OkHttp支持Http1/Http2/WebSocket协议,并在3.7版本中放弃了对Spdy协议,鼓励开发者使用Http/2。
在早期的版本中,OkHttp支持Http1.0,1.1,SPDY协议,但是Http2协议的问世,导致OkHttp也做出了改变,OkHttp鼓励开发者使用HTTP2,不再对SPDY协议给予支持。另外,新版本的OkHttp还有一个新的亮点就是支持WebScoket,这样我们就可以非常方便的建立长连接了。在安全方便,OkHttp目前支持了TLS版本,以确保一个安全的Socket连接。

2.3 Connection——连接层:管理网络连接,发送新的请求,接收服务器访问

连接层顾名思义就是负责网络连接。在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求;否则新创建一个网络连接。
虽然你只需要提供URL,但OkHttp计划它连接到您的网络服务器需要使用三种类型:URL,地址和路线.

  1. RealConnection:描述一个物理Socket连接,连接池中维护多个RealConnection实例。
  2. StreamAllocation: 由于Http/2支持多路复用,一个RealConnection可以支持多个网络访问请求,所以OkHttp又引入了StreamAllocation来描述一个实际的网络请求开销(从逻辑上一个Stream对应一个Call,但在实际网络请求过程中一个Call常常涉及到多次请求。如重定向,Authenticate等场景。所以准确地说,一个Stream对应一次请求,而一个Call对应一组有逻辑关联的Stream),一个RealConnection对应一个或多个StreamAllocation,所以StreamAllocation可以看做是RealConenction的计数器,当RealConnection的引用计数变为0,且长时间没有被其他请求重新占用就将被释放。

2.4 Cache——缓存层

Cache层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果,从而节省网络开销。

2.5 I/O层

I/O层负责实际的数据读写。OkHttp的另一大有点就是其高效的I/O操作,这归因于其高效的I/O库okio。

2.6 Inteceptor——拦截器层

拦截器是一种强大的机制,可以监视、重写和重试调用。拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。

猜你喜欢

转载自blog.csdn.net/zhangqilugrubby/article/details/80169374