OkHttp源码解析

简介

一、组成部分

OkHttpClient:是整个 OkHttp 的核心管理类,从面向对象的抽象表示上来看它代表了客户端本身,是请求的调用工厂,用来发送请求和读取响应。在大多数情况下这个类应该是被共享的,因为每个 Client 对象持有自己的连接池和线程池。重复创建则会造成在空闲池上的资源浪费。Client对象可以通过默认的无参构造方法创建也可以通过 Builder 创建自定义的 Client 对象。Client 持有的线程池和连接池资源在空闲时可以自动释放无需客户端代码手动释放,在特殊情况下也支持手动释放。

Request:一个 Request 对象代表了一个 Http 请求。它包含了请求地址 url,请求方法类型 method ,请求头 headers,请求体 body 等属性,该对象具有的属性普遍使用了 final 关键字来修饰,正如该类的说明文档中所述,当这个类的 body 为空或者 body 本身是不可变对象时,这个类是一个不可变对象。

Response:一个 Response 对象代表了一个 Http 响应。这个实例对象是一个不可变对象,只有 responseBody 是一个可以一次性使用的值,其他属性都是不可变的。

RealCal:一个 RealCall 对象代表了一个准备好执行的请求调用。它只能被执行一次。同时负责了调度和责任链组织的两大重任。

Dispatcher:调度器。它决定了异步调用何时被执行,内部使用 ExecutorService 调度执行,支持自定义 Executor。

EventListener:事件监听器。抽象类 EventListener 定义了在一个请求生命周期中记录各种事件的方法,通过监听各种事件,可以用来捕获应用程序 HTTP 请求的执行指标。从而监控 HTTP 调用的频率和性能。

Interceptor:拦截器。对应了软件设计模式中的拦截器模式,拦截器可用于改变、增强软件的常规处理流程,该模式的核心特征是对软件系统的改变是透明的和自动的。OkHttp 将整个请求的复杂逻辑拆分成多个独立的拦截器实现,通过责任链的设计模式将它们串联到一起,完成发送请求获取响应结果的过程。

二、执行流程

在这里插入图片描述

三、源码解析

1 请求封装

请求被封装成Call,请求动作由实现类RealCall执行

public interface Call extends Cloneable {
	//请求体
	Request request();
	//同步请求
	Response execute() throws IOException;
	//异步请求
	void enqueue(Callback responseCallback);
	//取消
	void cancel();
	boolean isExecuted();
	boolean isCanceled();
	Call clone();
	interface Factory {
	  Call newCall(Request request);
	}
}

final class RealCall implements Call {
	final OkHttpClient client;
	final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
	private EventListener eventListener;
	final Request originalRequest;
	final boolean forWebSocket;
	private boolean executed;
	
	private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
		this.client = client;
		//原始请求
		this.originalRequest = originalRequest;
		//是否WebSocket,用于长链接
		this.forWebSocket = forWebSocket;
		//重定向拦截器
		this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, 		forWebSocket);
	}
	
	static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
		// Safely publish the Call instance to the EventListener.
		RealCall call = new RealCall(client, originalRequest, forWebSocket);
		call.eventListener = client.eventListenerFactory().create(call);
		return call;
	}
}

//异步请求封装。就是个Rannable,执行getResponseWithInterceptorChain获取Response
final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

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

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    @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) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

3 调度器Dispatcher

  • readyAsyncCalls :缓存准备执行的异步请求
  • runningAsyncCalls :缓存正在执行的异步请求
  • runningSyncCalls :缓存正在执行的同步请求
  • executorService:无核心线程,阻塞队列为SynchronousQueue的线程池,这种线程池线程数量无上限,阻塞队列容量为0,适用于大量且立即执行的任务。类似CacheThreadPool。
public final class Dispatcher {
  private int maxRequests = 64;
  private int maxRequestsPerHost = 5;
  private @Nullable Runnable idleCallback;

  /** Executes calls. Created lazily. */
  private @Nullable ExecutorService executorService;

  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
  
  public synchronized ExecutorService executorService() {
    if (executorService == null) {
    	executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
}

executed():直接向runningSyncCalls队列中添加请求
enqueue(AsyncCall call):如果runningAsyncCalls数量小于64且runningAsyncCalls中与该请求同一主机的请求数小于5,就添加请求到runningAsyncCalls,并在线程池中执行。否则就把请求添加到readyAsyncCalls中。


synchronized void executed(RealCall call) {
  runningSyncCalls.add(call);
}

synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
}

3 拦截器种类

OkHttp 的核心功能是通过拦截器来实现的,各种拦截器的作用分别为:
client.interceptors:由开发者设置的拦截器,会在所有的拦截器处理之前进行最早的拦截处理,可用于添加一些公共参数,如自定义 header、自定义 log 等等。
RetryAndFollowUpInterceptor:主要负责进行重试和重定向的处理。
BridgeInterceptor:主要负责请求和响应的转换。把用户构造的 request 对象转换成发送到服务器 request对象,并把服务器返回的响应转换为对用户友好的响应。
CacheInterceptor:主要负责缓存的相关处理,将 Http 的请求结果放到到缓存中,以便在下次进行相同的请求时,直接从缓存中读取结果,提高响应速度。
ConnectInterceptor:主要负责建立连接,建立 TCP 连接或者 TLS 连接。
**client.networkInterceptors **:由开发者设置的拦截器,本质上和第一个拦截器类似,但是由于位置不同,所以用处也不同。
CallServerInterceptor:主要负责网络数据的请求和响应,也就是实际的网络I/O操作。将请求头与请求体发送给服务器,以及解析服务器返回的 response。

4 取消请求

@Override
	// 创建一个带 tag 的请求
    Request request = new Request.Builder()
            .url("https://api.example.com/data")
            .tag(REQUEST_TAG) // 设置请求标签
            .build();
            
    protected void onDestroy() {
        super.onDestroy();
        // 取消所有带有特定 tag 的请求
        cancelRequestsByTag(REQUEST_TAG);
    }
    
    private void cancelRequestsByTag(Object tag) {
        if (okHttpClient == null) return;
        
        for (Call call : okHttpClient.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        
        for (Call call : okHttpClient.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }

参考:
vivo互联网技术微信公众号

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值