Retrofit 源码解析

2019-03-04  本文已影响0人  一个不掉头发的开发

1. 功能介绍

1.1 Retrofit

Retrofit 是 Github 上面 squre 组织开发的一个类型安全的 Http 客户端,它可以在 Java 和 Android 上面使用。Retrofit 将描述请求的接口转换为对象,然后再由该对象去请求后台。Retrofit 将请求对象化了。目前已经发布了 2.0beta 版本。

1.2 特点

Retrofit 主要有以下功能特点

  1. 将 Http 请求对象化,函数化。让接口的函数代表具体请求。
  2. 利用注解的方式标记参数,将 HTTP 的请求方法,请求头,请求参数,请求体等等都用注解的方式标记,使用起来非常方便。
  3. 支持 Multipart,以及文件上传(file upload)。
  4. 直接将 Http 的 Response 转换成对象。用户可以根据 Response 的具体内容,更换转换器,或者自己新建转化器。
  5. Retrofit 默认使用 OkHttp 开源库请求后台,用户也可以使用自定义的具体请求方式。方便扩展。
  6. 自带提供了异步处理 Http 请求的方式。

1.3 简单 Demo

这是一个简单的例子,访问httpbin网站。也可以看完整的Retrofit Demo 首先声明一个 java 接口

使用方式

使用 httpbinService 获取一个 Call,用来请求 HTTP 服务器。

因为接口返回的应该是一个 Call,用来请求后台 HTPP 服务器,所以我们在声明接口的似乎,返回参数应该是 Call<?>。由于 httpbin 返回的是一个 json 格式的数据,我们想要返回直接的自定义的模型数据,但是 retrofit 默认只会返回 ResponseBody,所以我们需要自己添加一个 GsonConverter 第三方库。在 build.graddle 中的 dependencies 添加:

compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

2. 总体设计

Retrofit 可以分为注解解析(Request 生成),请求执行,请求回调(异步处理),响应体转化几个部分。其中请求执行与请求回调可以算作一个部分,并且请求回调也可以没有,Call 有直接执行的接口 execute。


  1. 首先由解析部分(这部分也是 Request 生成部分),利用注解(Annotation)解析接口文件,将接口方法解析好,每个方法生成一个 Request。
  2. 然后利用 Call 部分执行 Request。Retrofit 使用的是 okHttp 来请求,程序中将 Retrofit Request 转化为 OKHttp 开源库的 Request,转由 OkHttpClient 执行。
  3. 在 Request 执行完后,得到 Response,使用 Converter 转化 Response 为用户需要的对象。比如将 json 格式的数据,利用 gson 转化为具体的 Object(也就是接口函数中的返回 Call 的模版参数的具体类型对象)
  4. 利用回调将第三步得到的对象,将对象传回给 UI 线程,更新 UI。

这里面第三部与第四步是可以合在一起的,但是目前 Retrofit 提供的默认代码中,会通过 Call,加入 Callback,用户可以在 Callback 中处理结果。

注解(Annotation)是 Retrofit 预先定义的注解,包括 Http 的各个部分,比如 POST、GET、Query、QueryMap、Field 等等。

3. 流程图

其中生成 Call 的部分可以看下面关于这个适配器的类图。

4. 详细设计

4.1 类图

首先是整个项目的类图

对于 Retrofit 项目中 CallAdapter 用着适配器模式也挺巧的,通过适配器将 Callback 回调接口运行在 UI 线程。下面时有关 CallAdapter,Call,Callback 的类图,其中也是连续用了两次代理模式。

ExecutorCallback 代理的是用户自定义的 Callback。通过这种方式让 OkHttpCall 去执行 Call,让 ExecutorCallback 将用户自定义的 Callback 运行在指定线程上。

4.2 类功能详细介绍

在 Retrofit 开源库中,Retrofit 类是用户最基础的访问入口。然后 Converter 部分是由用户自己扩展的,而 Paraser 部分的相关类 RequestBuilder,RequestFactory 等则主要是负责解析接口并且生成 Request,而 Call,CallAdapter 等主要是负责底层的 Http 请求,以及请求后线程转换。

4.2.1 Retrofit

Retrofit 类是包含了一个构造器 Retrofit.Builder,由 Builder 指定 Retrofit 的相关参数,创建一个新的 Retrofit。Retrofit 中包含了很多重要的成员变量,而这些成员变量都是可以自设置的。

Retrofit 包含以下成员变量:

Retrofit 重要方法:

如果没有找到对应的 CallAdapterFactories,得到 CallAdapter,则该方法会抛出一个 IllegalArgumentException 异常,异常里面的 message 会是"Could not locate call adapter for ",如果遇到这个异常,则去判断对应的方法的返回类型是不是与 CallAdapterFactory 不匹配。

4.2.2 MethodHandler

MethodHandler 是 retrofit 中连接了解析部分,执行部分,转换部分的一个关键的中间类。不过 MethodHandler 的代码量很少。它可以说是连接各个部分的桥梁,也是接口方法的描述类。它有包含了 retrofit,requestFactory,callAdapter,responseConverter 成员变量。主要方法如下

4.2.3 Converter 与 Converter.Factory

这两个类别都是在 Converter 文件下。Converter 是接口,Factory 抽象类,很简短。

Factory 主要是负责生成两种 Converter。Retrofit 实现了一个简单的 BuiltInConverters。

4.2.4 Call

这是 Retrofit 的框架基础接口。它是 Retrofit 的发送请求给服务器并且返回响应体的调用。每个 Call 都有自己的 HTTP 请求和相匹配的响应。 它有如下四个接口:

4.2.5 CallAdapter

这是 Retrofit 的框架基础接口。CallAdapter 是将一个 Call 适配给另外一个 Call 的适配器接口。它有以下两个接口:

4.2.6 Callback

请求结构的回调接口。在 Call 的 enquene 接口中使用 有如下两个方法

4.2.7 OkHttpCall

实现了 Call 接口,但同样是模版类。首先介绍一下 OkHttpCall 的主要函数:

private com.squareup.okhttp.Call createRawCall() 根据由 requestFactory 根据 args 创建一个 Request,然后利用这个 Request 创建一个 okhttp.Call。

解析 okhttp.Response,

  1. 首先将 body 读取出来作为 rawBody,然后用 OkHttpCall.NoContentResponseBody 作为新的 Body,创建新的 rawResponse。
  2. 判断 Response.code(),如果不在 200 范围内,读取 rawBody 出来,返回一个错误的 retrofit 的 Response。如果 code 为 204 或 205(没有返回内容),则返回一个 body 为空的 retrofit 的 Response。
  3. 如果 code 正常,则用 OkHttpCall.ExceptionCatchingRequestBody 包装一下 rawBody, 然后使用 responseConverter 将包装后的 catchingBody 转化为具体的返回类型数据。

OkHttpCall 是将 Request 放入到 okhttp 的 Call 里面执行,执行完成后,又将 okhttp 的 Call 返回的 Response 转化为 retrofit 的 Response,在此同时将 Body 里面的内容,通过 converter 转化为对应的对象。这个 OkHttpCall

4.2.8 Response

这个类是包含了具体返回对象的响应体。里面包含了模版参数 T 类型的 body 对象,以及 okhttp 的 Response。

4.2.9 注解类

在 Retrofit 里面创建了 Body 注解,Filed 注解(Field,FieldMap),请求方法注解(DELETE,GET,PATCH,POST,PUT),请求头注解(HEAD,Header,Headers),multipart 注解(Part,Multipart,PartMap),接口加码(FormUrlEncoded),Url,Streaming,查询(Query,QueryMap),参数路径(Path),HTTP

4.2.10 RequestBuilderAction

这是一个抽象类,只有一个未实现的 perform 方法。

abstract void perform(RequestBuilder builder, Object value);

但是在 RequestBuilderAction 类里面有很多 RequestBuilderAction 的子类,分别对应注解类。Url,Header,Path,Query,QueryMap,Field,FieldMap,Part,PartMap,Body 都是在 RequestBuilderAction 的内部类,并且继承了 RequestBuilderAction。RequestBuilder 就是将对应注解的值给 RequestBuilder。

4.2.11 RequestBuilder

这是一个 okhttp.Request 的创建类。负责设置 HTTP 请求的相关信息,创建 Request。它主要有以下方法:

它的构造方法如下: RequestBuilder(String method, HttpUrl baseUrl, String relativeUrl, Headers headers, MediaType contentType, boolean hasBody, boolean isFormEncoded, boolean isMultipart)

RequestBuilder 就是创建请求。

4.2.12 RequestFactory

RequestFactory 是创建 Request,他有个 create 方法,

Request create(Object... args) {

参数是接口函数对应的参数值,cerate 是创建 RequestBuilder,遍历 RequestFactory 的成员变量 requestBuilderActions,设置好 RequestBuilder,最后创建 Request 返回。

4.2.13 RequestFactoryParser

这个类主要是接口函数 Method 的每个注解。入口函数是 parse。

先解析方法注解(应用到方法上的注解),比如说 FormUrlEncoded,Headers。得到对应的值。

然后再解析方法参数注解(应用到方法参数上的注解),在解析方法参数注解的时候,会生成一个 requestBuilderActions 数组,对应到每个参数。每个 Action 都对应了每个函数参数的处理。等到具体函数调用的时候,跟函数具体的参数值对应。也就是 RequestFactory 与 Builder 的工作了,这部分是等到运行的时候才能够确定的。

4.2.14 BuiltInConverters,OkHttpResponseBodyConverter,VoidConverter,OkHttpRequestBodyConverter

BuiltInConverters 继承自 Converter.Factory,返回的 responseConverter 是 OkHttpResponseBodyConverter 或 VoidConverter,也就是接口方法返回的职能是 OkHttp 的 ResponseBody,或者 Void。 返回的 requestConverter 是 OkHttpRequestBodyConverter,接口方法的参数中如果使用 Body,那 Body 也只能是 OkHttp 的 RequestBody。

VoidConverter: 将 OkHttp 的 ResponseBody 转化为 Void。 OkHttpResponseBodyConverter:将 OkHttp 的 ResponseBody 转化为 OkHttp 的 ResponseBody。如果是 Streaming 标记的接口的话,利用 Utils.readBodyToBytesIfNecessary 缓冲整个 body。 OkHttpRequestBodyConverter:将 OkHttp 的 RequestBody 转化为 OkHttp 的 RequestBody。

4.2.15 PlatForm.Android.MainThreadExecutor

一个 Executor,通过 android Handler 将 Runnable 执行在 UI 线程中。

4.2.16 Utils

这是 Retrofit 中的一个工具类,里面包含了很多范型的检查、操作。另外以及一些基本的工具性的功能。下面是它里面的函数:

4.3 扩展

Retrofit 是很适合扩展的,里面设计的 Call,以及 Converter 就是为了方便扩展使用。

4.3.1 Converter

Retrofit 提供的默认的 Converter 只会返回 ResponseBody,如果我们想要返回具体的 Object,我们可以使用另外的第三方包,并且在创建 Retrofit 的时候添加对应的 ConverterFactory。这里有 6 个序列化第三方库:

4.3.2 Rxjava

retrofit 也可以与Rxjava联合起来使用,之前的版本使用范例可以参考http://randomdotnext.com/retrofit-rxjava/

正在开发中,主要是通过扩展 CallAdapter,将之前 Call,转换为 rxjava 需要的 Observable<?>。

5 说明

这篇文章不是我写的,本文补全了好多我之前对Retrofit的遗漏知识,所以复制粘贴下来当作笔记,如果其他同学看到,还请多看原作者的原文章:https://github.com/android-cn/android-open-project-analysis/tree/master/tool-lib/network/retrofit

上一篇下一篇

猜你喜欢

热点阅读