0
点赞
收藏
分享

微信扫一扫

Android 10分钟从源码解读OkHttp

承蒙不弃 2021-09-23 阅读 45

OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。对于 Android App 来说,OkHttp 现在几乎已经占据了所有的网络请求操作,因此它也是每一个 Android 开发工程师的必备技能,了解其内部实现原理可以更好地进行功能扩展、封装以及优化。

适用于 Android 和 Java 应用程序的 HTTP 和 HTTP/2 客户端。

OkHttp的4.0.x版本已经全部由java替换到了Kotlin,API的一些使用也会有些不同。

要求

支持的版本

4.0.x:Android 5.0+(API 级别 21+)和 Java 8+。

3.12.x:Android 2.3+(API 级别 9+)和 Java 7+。平台可能不支持 TLSv1.2。(2021-12-31不再支持)

OkHttp有一个库的依赖Okio,用于高性能I/O一个小型library。它适用于 Okio 1.x(用 Java 实现)或 Okio 2.x(升级到 Kotlin)。

本文使用的OkHttp的版本为3.14.2,不是不会接入高版本,主要是4.0.x版本已经全部由java替换到了Kotlin,Kotlin不太熟怕理解错了,误导人民群众。

网络请求流程分析

OkHttp 经过几次迭代后,已经发生了很多变化。更好地 WebSocket 支持、更多的 Interceptor 责任链,甚至连最核心的 HttpEngine 也变成了 HttpCodec。本文会重新梳理整个网络请求的流程,以及实现机制。

先看下 OkHttp 的基本使用:

除了直接 new OkHttpClient 之外,还可以使用内部工厂类 Builder 来设置 OkHttpClient。如下所示:

请求操作的起点从 OkHttpClient.newCall().enqueue() 方法开始:

这个方法会返回一个RealCall 对象,通过它将网络请求操作添加到请求队列中。

client.dispatcher()返回Dispatcher,调用 Dispatcher 的 enqueue 方法,执行一个异步网络请求的操作。

Dispatcher 是 OkHttpClient 的调度器,是一种门户模式。主要用来实现执行、取消异步请求操作。本质上是内部维护了一个线程池去执行异步操作,并且在 Dispatcher 内部根据一定的策略,保证最大并发个数、同一 host 主机允许执行请求的线程个数等。

实际上就是使用线程池执行了一个 AsyncCall,而 AsyncCall 继承了NamedRunnable,NamedRunnable 实现了 Runnable 接口,因此整个操作会在一个子线程(非 UI 线程)中执行。

在 run 方法中执行了 一个抽象方法execute这个抽象方法被AsyncCall实现。

从上面看出而真正获取请求结果的方法是在getResponseWithInterceptorChain方法中,从名字也能看出其内部是一个拦截器的调用链。

Interceptor:拦截器是一种强大的机制,可以监视、重写和重试调用。

每一个拦截器的作用如下:

BridgeInterceptor:主要对 Request 中的 Head 设置默认值,比如 Content-Type、Keep-Alive、Cookie 等。

CacheInterceptor:负责 HTTP 请求的缓存处理。

ConnectInterceptor:负责建立与服务器地址之间的连接,也就是 TCP 链接。

CallServerInterceptor:负责向服务器发送请求,并从服务器拿到远端数据结果。

RetryAndFollowUpInterceptor:此拦截器从故障中恢复,并根据需要执行重定向。如果呼叫被取消,它可能会引发IOException。

在添加上述几个拦截器之前,会调用 client.interceptors 将开发人员设置的拦截器添加到列表当中。

对于 Request 的 Head 以及 TCP 链接,我们能控制修改的成分不是很多。所以咱们了解CacheInterceptorCallServerInterceptor

CacheInterceptor 缓存拦截器

CacheInterceptor 主要做以下几件事情: a. 根据 Request 获取当前已有缓存的 Response(有可能为 null),并根据获取到的缓存 Response,创建 CacheStrategy 对象。

通过 Cache 实现缓存功能

通过上面缓存拦截器的流程可以看出,OkHttp 只是规范了一套缓存策略,但是具体使用何种方式将数据缓存到本地,以及如何从本地缓存中取出数据,都是由开发人员自己定义并实现,并通过 OkHttpClient.Builder 的 cache 方法设置。

OkHttp 提供了一个默认的缓存类 Cache.java,我们可以在构建 OkHttpClient 时,直接使用 Cache 来实现缓存功能。只需要指定缓存的路径,以及最大可用空间即可,如下所示:

DiskLruCache 最终会将需要缓存的数据保存在本地。如果感觉 OkHttp 自带的这套缓存策略太过复杂,我们可以设置使用 DiskLruCache 自己实现缓存机制。

LRU:是近期最少使用的算法(缓存淘汰算法),它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有两种:LrhCache和DisLruCache,分别用于实现内存缓存和硬盘缓存,其核心思想都是LRU缓存算法。

CallServerInterceptor 详解

CallServerInterceptor 是 OkHttp 中最后一个拦截器,也是 OkHttp 中最核心的网路请求部分。

    上面是向服务器端发送请求数据

  下面是从服务端获取相应数据

    并构建 Response 对象

小结

1、OkHttp 内部是一个门户模式,所有的下发工作都是通过一个门户 Dispatcher 来进行分发。

2、网络请求阶段通过责任链模式,链式的调用各个拦截器的 intercept 方法。本文重点介绍了 2 个比较重要的拦截器:CacheInterceptor(请求缓存) 和 CallServerInterceptor(执行网络请求)。

举报

相关推荐

0 条评论