当前位置: 首页 > news >正文

OkHttp源码解析(一)

一、使用流程

二、分发器

import androidx.annotation.Nullable;import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.ExecutorService;// 可根据需要替换/补充 AsyncCall 与 RealCall 的定义
public final class DispatcherLike {// 异步请求同时存在的最大请求private int maxRequests = 64;// 异步请求同一域名同时存在的最大请求private int maxRequestsPerHost = 5;// 闲置任务(没有请求可执行时执行一些任务,由使用者设置)@Nullableprivate Runnable idleCallback;// 异步请求使用的线程池@Nullableprivate ExecutorService executorService;// 异步请求等待执行队列private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();// 异步请求正在执行队列private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();// 同步请求正在执行队列private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();// 根据实际需求添加构造方法、setter/getter、调度逻辑等// ...
}

三、同步请求

四、异步请求

// 异步请求调用
public void finished(AsyncCall call) {finished(runningAsyncCalls, call, true);
}// 同步请求调用
public void finished(RealCall call) {finished(runningSyncCalls, call, false);
}private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {int runningCallsCount;Runnable idleCallback;synchronized (this) {// 不管异步还是同步,执行完后都要从队列移除if (!calls.remove(call)) {throw new AssertionError("Call wasn't in-flight!");}if (promoteCalls) {promoteCalls();}// 异步任务和同步任务正在执行的和runningCallsCount = runningCallsCount();idleCallback = this.idleCallback;}// 没有任务执行时执行闲置回调if (runningCallsCount == 0 && idleCallback != null) {idleCallback.run();}
}

五、请求流程

用户是不需要直接操作任务分发器的,获得的 RealCall 中就分别提供了 execute enqueue 来开始同步请求或异 步请求。
@Override
public Response execute() throws IOException {synchronized (this) {if (executed) throw new IllegalStateException("Already Executed");executed = true;}captureCallStackTrace();eventListener.callStart(this);try {// 调用分发器client.dispatcher().executed(this);// 执行请求Response result = getResponseWithInterceptorChain();if (result == null) throw new IOException("Canceled");return result;} catch (IOException e) {eventListener.callFailed(this, e);throw e;} finally {// 请求完成client.dispatcher().finished(this);}
}

import java.io.IOException;final class AsyncCall extends NamedRunnable {private final Callback responseCallback;AsyncCall(Callback responseCallback) {super("OkHttp %s", redactedUrl());this.responseCallback = responseCallback;}// 线程池执行@Overrideprotected void execute() {boolean signalledCallback = false;try {Response response = getResponseWithInterceptorChain();// ......} catch (IOException e) {// ......} finally {// 请求完成client.dispatcher().finished(this);}}private static String redactedUrl() { return "url"; }private Response getResponseWithInterceptorChain() throws IOException { return new Response(); }private final OkHttpClient client = new OkHttpClient();
}public abstract class NamedRunnable implements Runnable {protected final String name;public NamedRunnable(String format, Object... args) {this.name = Util.format(format, args);}@Overridepublic final void run() {String oldName = Thread.currentThread().getName();Thread.currentThread().setName(name);try {execute();} finally {Thread.currentThread().setName(oldName);}}protected abstract void execute();
}

六、分发器线程池

前面我们提过,分发器就是来调配请求任务的,内部会包含一个线程池。当异步请求时,会将请求任务交给线程池 来执行。那分发器中默认的线程池是如何定义的呢?为什么要这么定义?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;private ExecutorService executorService;public synchronized ExecutorService executorService() {if (executorService == null) {executorService = new ThreadPoolExecutor(0,                              // 核心线程Integer.MAX_VALUE,              // 最大线程60L,                            // 空闲线程闲置时间TimeUnit.SECONDS,               // 闲置时间单位new SynchronousQueue<Runnable>(), // 线程等待队列Util.threadFactory("OkHttp Dispatcher", false) // 线程创建工厂);}return executorService;
}

七、拦截器责任链

OkHttp最核心的工作是在 getResponseWithInterceptorChain() 中进行,在进入这个方法分析之前,我们先来了 解什么是责任链模式,因为此方法就是利用的责任链模式完成一步步的请求。

责任链模式

为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。在这种模式 中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下 一个接收者,依此类推。比如:

八、拦截器流程

请求会被交给责任链中的一个个拦截器。默认情况下有五大拦截器:
1. RetryAndFollowUpInterceptor
第一个接触到请求,最后接触到响应;负责判断是否需要重新发起整个请求
2. BridgeInterceptor
补全请求,并对响应进行额外处理
3. CacheInterceptor
请求前查询缓存,获得响应并判断是否需要缓存
4. ConnectInterceptor
与服务器完成TCP连接
5. CallServerInterceptor
与服务器通信;封装请求数据与解析响应数据(如:HTTP报文)
http://www.dtcms.com/a/478302.html

相关文章:

  • 拆分PDF.html 办公小工具
  • 网站编辑用什么软件有关于网站建设类似的文章
  • 陶瓷网站制作wordpress导购主题
  • 分割——双线性插值
  • 北京天仪建设工程质量检测所网站上海做网站的公司电话
  • 建站优化一条龙新闻型网站建设
  • Petslist – Pet listing WordPress Theme Free Download
  • STM32 GPIO-------设置成51单片机模式输出
  • C++之多层继承、多源继承、菱形继承
  • 双目三维重建-1相机标定
  • GIT 提示 remote: HTTP Basic: Access denied
  • 建设门户网站都需要什么成都网站设计新闻
  • 徐州贾汪区建设局网站资兴市住房和城乡建设局网站
  • 黄江仿做网站企业管理系统多少钱
  • 机器学习-推荐系统(下)
  • 「机器学习笔记13」无监督学习全面解析:从聚类算法到Python实战
  • 计算机视觉(opencv)——基于MediaPipe与机器学习的手势识别系统
  • 建设网站的请示如何做漂亮的网站
  • 【C++ 学习】单词统计器:从 “代码乱炖” 到 “清晰可品” 的复习笔记
  • STL分解:从定义到实战
  • 自己写算法(九)网页数字动画函数——东方仙盟化神期
  • 郑州市科协网站小程序可以用手机网站吗
  • 创建一个 Vue3项目
  • 使用远程模拟器开发调试安卓APP
  • Java外功精要(3)——Spring配置文件和mybatis
  • 深圳网站建设服务商万创网为女足世界杯创建一个网站
  • Vmware Workstation虚拟机不能拖动复制文件到宿主机的Bug原因探究过程
  • 嵌入式Linux开发环境学习(一)
  • 三种解法(数组、栈、快慢指针)全面解析——力扣234.回文链表全解析
  • linux 系统压力测试工具stress使用