深入剖析 Android 网络开源库 Retrofit 的源码详解

文章目录

  • 概述
  • 一、Retrofit 简介
    • Android主流网络请求库
  • 二、Retrofit 源码剖析
    • 1. Retrofit 网络请求过程
    • 2. Retrofit 实例构建
      • 2.1 Retrofit.java
      • 2.2 Retrofit.Builder()
        • 2.2.1 Platform.get()
        • 2.2.2 Android 平台
      • 2.3 Retrofit.Builder().baseUrl()
      • 2.4 Retrofit.Builder.client()
      • 2.5 Retrofit.Builder.addConverterFactory()
        • 2.5.1 GsonConverterFactory.create()
      • 2.6 Retrofit.Builder.addCallAdapterFactory()
        • 2.6.1 RxJava2CallAdapterFactory.create()
      • 2.7 Retrofit.Builder.build()
    • 3. Retrofit 创建网络请求接口实例
      • 3.1 Retrofit.create()
      • 3.2 Retrofit.loadServiceMethod()
      • 3.3 ServiceMethod.parseAnnotations()
        • 3.3.1 RequestFactory.parseAnnotations()
      • 3.4 HttpServiceMethod.parseAnnotations()
        • 3.4.1 HttpServiceMethod.createCallAdapter()
        • 3.4.2 Retrofit.callAdapter()
        • 3.4.3 HttpServiceMethod.createResponseConverter()
        • 3.4.4 Retrofit.responseBodyConverter()
        • 3.4.5 GsonConverterFactory.responseBodyConverter()
        • 3.4.6 GsonResponseBodyConverter
      • 3.5 HttpServiceMethod
      • 3.6 OkHttpCall
      • 3.7 RxJava2CallAdapter.adapt()
      • 小结
    • 4. Retrofit 执行网络请求
      • 4.1 Observable.subscribe()
      • 4.2 BodyObservable.subscribeActual()
      • 4.3 CallObservable.subscribeActual()
      • 4.4 OkHttpCall.execute()
        • 4.4.1 RequestFactory.create()
        • 4.4.2 OkHttpClient.newCall()
        • 4.4.3 RealCall.newRealCall()
      • 4.5 OkHttpCall.parseResponse()
        • 4.5.1 GsonResponseBodyConverter.convert()
        • 4.5.2 Gson.getAdapter()
        • 4.5.3 ReflectiveTypeAdapterFactory.Adapter.read()
      • 4.6 Response.success()
    • 小结
  • 总结
  • 参考


概述

Android 开发中,通过网络请求获取服务端数据是一项基本且常见的需求。目前有多种网络请求框架可供选择,其中 Android-Async-HttpVolleyOkHttpRetrofit 是较为流行的、开源的网络请求框架。如何选择它们?孰优孰劣?仁者见仁智者见智,我个人觉得适合的就是最好的,不要盲目跟风去更换掉之前选用的网络请求框架,毕竟老代码那是牵一发而动全身哈!对于新项目来说,选择一个好用的网络请求框架,还是很有必要的,而 Retrofit 作为当下最火的一个网络开源请求库,还是值得学习并尝试使用的。


一、Retrofit 简介

Retrofit 是一个在 Android 开发中常用的网络请求框架。是 Square 公司基于他们自己的另一个比较火的网络库 OkHttp,进行封装的一个 RESTfulHTTP 网络请求框架。其提供了简洁而强大的 API,用于与 RESTful 服务进行通信。

  • App 应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、HeaderUrl 等信息,之后由 OkHttp 完成后续的请求操作;
  • 请求获取到服务端的响应后,OkHttp 将服务端返回的、原始的数据交给 RetrofitRetrofit 再根据用户的需求对结果进行解析。

Retrofit 的一些主要特点和优势:

  • 简单易用的 APIRetrofit 提供了简洁、直观的 API,使得定义和执行网络请求变得非常简单。通过定义接口,并使用注解来描述请求参数和响应数据,可以轻松地与 RESTful API 进行交互;
  • 自动化网络请求处理Retrofit 处理了大部分网络请求的细节,包括请求的构建、执行、响应的解析等,大大简化了网络请求的代码编写过程;
  • 内置支持 RxJavaRetrofit 2.0 内置支持 RxJava,可以方便地将网络请求转换为 ObservablesSingles,实现更加优雅的异步编程模式;
  • 请求和响应的数据转换Retrofit 支持多种数据格式的转换,包括:GsonJSONXMLProtobuf 等,可以方便地进行数据的序列化和反序列化;
  • 灵活的请求配置Retrofit 允许你配置全局的请求参数,包括:连接超时读取超时请求头日志输出等,以满足不同场景下的需求;
  • 强大的错误处理机制Retrofit 提供了灵活的错误处理机制,可以根据不同的 HTTP 状态码和错误情况进行统一处理,使得应用程序在遇到错误时能够优雅地处理并给出相应的提示。

Retrofit 与其它主流网络请求库之间的功能与区别:

Android主流网络请求库

二、Retrofit 源码剖析

1. Retrofit 网络请求过程

Retrofit 请求网络的过程
结合上图,解释一下 Retrofit 网络请求过程:

  1. 通过解析网络请求接口的注解配置网络请求参数
  2. 通过动态代理生成网络请求对象
  3. 通过网络请求适配器将网络请求对象进行平台适配(包括:AndroidRxJavaGuavaJava8
  4. 通过网络请求执行器发送网络请求
  5. 通过数据转换器解析服务器返回的数据
  6. 通过回调执行器切换线程(子线程切到主线程)
  7. 用户在主线程处理并展示返回结果

本文不准备详细介绍 Retrofit 的使用,主要是深入源码剖析其原理,下面就根据上面的请求过程,逐步剖析 Retrofit 的源码调用过程,注意:后续的源码基于 Retrofit 2.5.0 版本进行分析。

2. Retrofit 实例构建

Retrofit 实例是使用建造者模式通过 Builder 类进行创建的:

OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new TokenHeaderInterceptor()) // 动态添加token.addInterceptor(new NullResponseInterceptor()) // 返回空字符的时候显示.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS).writeTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS).readTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS).build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(mBaseUrl).client(client) // okhttp实例对象.addConverterFactory(GsonConverterFactory.create()) // 添加转换器工厂.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 请求指定适配器 RxJava.build();

2.1 Retrofit.java

public final class Retrofit {// 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)// 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();// 网络请求执行器的工厂,其作用是生产网络请求执行器 Call,Retrofit 默认使用 OkHttpfinal okhttp3.Call.Factory callFactory;final HttpUrl baseUrl; // 网络请求的 url 基地址// 存放数据转换器工厂的集合,数据转换器工厂是用来生产数据转换器(Converter)final List<Converter.Factory> converterFactories;// 存放网络请求适配器工厂的集合,网络请求适配器工厂是用来生产网络请求适配器(CallAdapter)final List<CallAdapter.Factory> callAdapterFactories;final @Nullable Executor callbackExecutor; // 回调方法执行器// 是否提前对业务接口中的注解进行验证转换的标志位final boolean validateEagerly;Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,@Nullable Executor callbackExecutor, boolean validateEagerly) {this.callFactory = callFactory;this.baseUrl = baseUrl;this.converterFactories = converterFactories; // Copy+unmodifiable at call site.this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.this.callbackExecutor = callbackExecutor;this.validateEagerly = validateEagerly;}
}

通过 Retrofit 的构造函数构建一个 Retrofit 实例对象,并配置好类里面的各成员变量。

工厂模式:设计模式中工厂模式,是将”类实例化的操作”与“使用对象的操作”分开,使得使用者不用知道具体参数就可以实例化出所需要的“产品”类。

2.2 Retrofit.Builder()

public final class Retrofit {public static final class Builder {private final Platform platform;private @Nullable okhttp3.Call.Factory callFactory;private @Nullable HttpUrl baseUrl;private final List<Converter.Factory> converterFactories = new ArrayList<>();private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();private @Nullable Executor callbackExecutor;private boolean validateEagerly;Builder(Platform platform) {this.platform = platform;}public Builder() {// 继续调用自身有参的构造方法,并通过调用 Platform.get() 方法传入了 Platform 对象this(Platform.get());}}
}

静态内部类 Builder 的成员变量与 Retrofit 类的成员变量是对应的,通过 Builder 类对 Retrofit 类的成员变量进行赋值。

建造者模式:将一个复杂对象的构建与表示分离,使得用户在不知道对象的创建细节情况下就可以直接创建复杂的对象。

2.2.1 Platform.get()
class Platform {private static final Platform PLATFORM = findPlatform();static Platform get() {// PLATFORM 是一个静态的 final 类型的变量,通过 findPlatform() 方法来赋值return PLATFORM;}private static Platform findPlatform() {try {// 通过 Class.forName(),JVM 查找并加装指定的类(即 Java 会执行该类的静态代码段)Class.forName("android.os.Build");if (Build.VERSION.SDK_INT != 0) {// 如果是 Android 平台,就创建并返回一个 Android 对象并返回return new Android();}} catch (ClassNotFoundException ignored) {}try {// 支持 Java 8Class.forName("java.util.Optional");return new Java8();} catch (ClassNotFoundException ignored) {}return new Platform();}
}

由 Platform.get() 方法可以看出,Retrofit 2.5 目前支持 AndroidJava 平台,翻看之前 2.0 版本的代码,那会儿还支持 iOS 平台。在方法中通过判断返回对应平台的实例对象,这里返回的是 Android 的实例对象,即指定了运行平台为 Android

2.2.2 Android 平台
class Platform {static class Android extends Platform {@Override public Executor defaultCallbackExecutor() {// 新建并返回 MainThreadExecutor 实例作为默认的回调方法执行器return new MainThreadExecutor();}// Retrofit 中提供了四种 CallAdapterFactory:ExecutorCallAdapterFactory(默认)、// GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(@Nullable Executor callbackExecutor) {if (callbackExecutor == null) throw new AssertionError();// 创建默认的网络请求适配器工厂,生产的 adapter 使得 Call 在异步调用时在指定的 Executor 上执行回调ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);return Build.VERSION.SDK_INT >= 24? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory): singletonList(executorFactory);}@Override int defaultCallAdapterFactoriesSize() { // 默认请求适配器工厂数量return Build.VERSION.SDK_INT >= 24 ? 2 : 1; // 大于7.0 2 个 其他 1 个}@Override List<? extends Converter.Factory> defaultConverterFactories() { // 默认转换器工厂return Build.VERSION.SDK_INT >= 24? singletonList(OptionalConverterFactory.INSTANCE): Collections.<Converter.Factory>emptyList();}@Override int defaultConverterFactoriesSize() { // 默认转换器数量return Build.VERSION.SDK_INT >= 24 ? 1 : 0; // 大于7.0 1 个 其他 0 个}static class MainThreadExecutor implements Executor {// 使用 Android 主线程的 Looper 来新建一个 Handlerprivate final Handler handler = new Handler(Looper.getMainLooper());@Override public void execute(Runnable r) {// 通过上面新建的 Handler 发送消息,将消息发送到UI主线程,在UI线程对网络请求返回数据进行处理handler.post(r);}}}
}

至此,RetrofitBuilder 类介绍完毕,通过跟踪查看代码可知,在 Builder 类中设置了默认的平台类型对象:Android、网络请求适配器工厂:CallAdapterFactoryCallAdapter 用于对原始 Call 进行再次封装,如结合 RxJava 使用时将 Call 封装成 Observable)、数据转换器工厂:ConverterFactory 和回调执行器:CallbackExecutor

注意:这里只是设置了默认值,但未真正配置到具体的 Retrofit 类的成员变量当中。

2.3 Retrofit.Builder().baseUrl()

public final class Retrofit {public static final class Builder {......private @Nullable HttpUrl baseUrl;......// 配置 Retrofit 类的网络请求基地址 baseUrlpublic Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 通过 HttpUrl.get() 方法把 String 类型的 url 参数转化为适合 OkHttp 的 HttpUrl 类型return baseUrl(HttpUrl.get(baseUrl));}public Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 把 baseUrl 参数分割成几个路径碎片List<String> pathSegments = baseUrl.pathSegments();// 通过检测最后一个 Segment 来检查 baseUrl 参数是不是以"/"结尾,不是则抛出异常if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);}this.baseUrl = baseUrl;return this;}}
}

通过 HttpUrl.get() 方法把 String 类型的 url 参数转化为适合 OkHttpHttpUrl 类型,然后调用 baseUrl() 方法传入刚转化的 HttpUrl,并通过检测最后一个 Segment 来检查传入的参数是不是以 “/” 结尾,如果是则赋值保存传入的 HttpUrl,不是则抛出异常。

2.4 Retrofit.Builder.client()

public final class Retrofit {public static final class Builder {private @Nullable okhttp3.Call.Factory callFactory;......// 用于请求的 HTTP 客户端,OkHttpClient 是 Call.Factory 接口的实现类public Builder client(OkHttpClient client) {return callFactory(checkNotNull(client, "client == null"));}// 为创建 Call 实例指定一个自定义调用工厂,设置 client 时自动设置 Call.Factorypublic Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;}}
}

Retrofit.Builder.client() 方法为创建网络请求 Call 指定一个自定义调用工厂,这里注意:OkHttpClientCall.Factory 接口的实现类。

2.5 Retrofit.Builder.addConverterFactory()

public final class Retrofit {public static final class Builder {......private final List<Converter.Factory> converterFactories = new ArrayList<>();......// 为对象的序列化和反序列化添加数据转换器工厂public Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;}}
}

Builder.addConverterFactory() 方法为对象的序列化和反序列化添加数据转换器工厂 ConverterFactory,下面以 GsonConverterFactory 为例,调用 GsonConverterFactory.create() 方法来创建实例对象。

2.5.1 GsonConverterFactory.create()
public final class GsonConverterFactory extends Converter.Factory {// 使用默认的 Gson 实例创建一个 GsonConverterFactory 实例用于数据转换// 编码到 JSON 并从 JSON 解码(当头部没有指定字符集时)将使用UTF-8public static GsonConverterFactory create() {// 继续调用重载的 create() 方法并传入一个新建的 Gson 实例return create(new Gson());}// 重载的 create() 方法,作用与上面的类似@SuppressWarnings("ConstantConditions") // Guarding public API nullability.public static GsonConverterFactory create(Gson gson) {if (gson == null) throw new NullPointerException("gson == null");// 创建一个含有 Gson 实例对象的 GsonConverterFactoryreturn new GsonConverterFactory(gson);}private final Gson gson;private GsonConverterFactory(Gson gson) {this.gson = gson;}@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,Retrofit retrofit) {TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));return new GsonResponseBodyConverter<>(gson, adapter);}@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));return new GsonRequestBodyConverter<>(gson, adapter);}
}

GsonConverterFactory.creat() 方法中创建了一个含有 Gson 实例的 GsonConverterFactory 实例对象, 并返回给 Builder.addConverterFactory() 方法作为方法的入参将其放入到 converterFactories 集合中。

2.6 Retrofit.Builder.addCallAdapterFactory()

public final class Retrofit {public static final class Builder {......private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();......// 添加网络请求 Call 的适配器工厂,以支持除 Call 以外的服务方法返回类型public Builder addCallAdapterFactory(CallAdapter.Factory factory) {callAdapterFactories.add(checkNotNull(factory, "factory == null"));return this;}}
}

Builder.addCallAdapterFactory() 方法为网络请求 Call 添加适配器工厂,以支持除 Call 以外的服务方法返回类型。本文以 RxJava2CallAdapterFactory 为例,调用 RxJava2CallAdapterFactory.create() 方法来创建实例对象。

2.6.1 RxJava2CallAdapterFactory.create()
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {public static RxJava2CallAdapterFactory create() {// 继续调用 RxJava2CallAdapterFactory 有参构造方法,只是 Scheduler 传入为 nullreturn new RxJava2CallAdapterFactory(null);}private final Scheduler scheduler;private RxJava2CallAdapterFactory(Scheduler scheduler) {this.scheduler = scheduler;}@Overridepublic CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {Class<?> rawType = getRawType(returnType); // 获取当前方法参数的具体类型if (rawType == Completable.class) { // 返回类型是否是Completable类// Completable 没有参数化(这是该方法的其余部分所处理的),因此只能用单个配置创建它return new RxJava2CallAdapter(Void.class, scheduler, false, true, false, false, false, true);}// 由于本文是结合 RxJava 进行使用的,因此返回值类型是 Observable 类型的boolean isFlowable = rawType == Flowable.class; // isFlowable 为 falseboolean isSingle = rawType == Single.class; 	// isSingle 为 falseboolean isMaybe = rawType == Maybe.class; 		// isMaybe 为 falseif (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {return null; // 不是 Completable、Flowable、Single、Maybe 和 Observable 则返回 null}boolean isResult = false;boolean isBody = false;Type responseType;if (!(returnType instanceof ParameterizedType)) { // 非参数化类型String name = isFlowable ? "Flowable" : isSingle ? "Single" : "Observable";throw new IllegalStateException(name + " return type must be parameterized"+ " as " + name + "<Foo> or " + name + "<? extends Foo>");}// 获取泛型参数的上界Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);Class<?> rawObservableType = getRawType(observableType); // 获取当前方法参数的具体类型if (rawObservableType == Response.class) { // 如果是 Responseif (!(observableType instanceof ParameterizedType)) { // 非参数化类型 抛出异常throw new IllegalStateException("Response must be parameterized"+ " as Response<Foo> or Response<? extends Foo>");}// 获取当前返回类型的具体类型responseType = getParameterUpperBound(0, (ParameterizedType) observableType);} else if (rawObservableType == Result.class) { // 如果是 Result if (!(observableType instanceof ParameterizedType)) { // 非参数化类型 抛出异常throw new IllegalStateException("Result must be parameterized"+ " as Result<Foo> or Result<? extends Foo>");}// 获取当前返回类型的具体类型responseType = getParameterUpperBound(0, (ParameterizedType) observableType);isResult = true;} else { // 如果都不符合,则默认情况下返回值类型为 observableTyperesponseType = observableType;isBody = true; // isBody 置为 true}// 根据上面的值,实例化 RxJava2CallAdapter 对象return new RxJava2CallAdapter(responseType, scheduler, isResult, isBody, isFlowable,isSingle, isMaybe, false);}
}

RxJava2CallAdapterFactory.creat() 方法中创建 RxJava2CallAdapterFactory 实例对象, 并返回给 Builder.addCallAdapterFactory() 方法作为方法的入参将其放入到 callAdapterFactories 集合中。

2.7 Retrofit.Builder.build()

public final class Retrofit {public static final class Builder {......private @Nullable HttpUrl baseUrl;......Builder(Platform platform) {this.platform = platform;}/*** 使用配置的值创建 Retrofit 实例* 注意:如果 client() 方法和 callFactory() 方法都没有被调用,那么默认的 OkHttpClient 将被创建和使用*/public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) { // 如果没有指定 callFactory,则创建并配置默认的网络请求执行器 OkHttpClientcallFactory = new OkHttpClient();}Executor callbackExecutor = this.callbackExecutor;if (callbackExecutor == null) {// 如果没有指定 callbackExecutor,则使用 platform 默认的回调执行器// Android 平台默认是 MainThreadExecutorcallbackExecutor = platform.defaultCallbackExecutor();}// 创建 CallAdapterFactory 的副本,并将 platform 默认的 CallAdapterFactories 添加到集合的末尾// 即 CallAdapterFactory 存储顺序:自定义 CallAdapterFactory 根据添加顺序优先执行,默认的 CallAdapterFactory 最后执行List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));// 创建 ConverterFactory 的副本,其集合的长度 size 是 platform 默认的 defaultConverterFactoriesSize// 加上当前 this.converterFactories.size() 再加 1List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());// 首先添加内置的转换器工厂,其次是 GsonConverterFactory(添加到集合的第二位),最后是platform默认的 defaultConverterFactoriesconverterFactories.add(new BuiltInConverters());converterFactories.addAll(this.converterFactories);converterFactories.addAll(platform.defaultConverterFactories());// 新建并返回一个 Retrofit 实例对象,传入上述已经配置好的成员变量return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);}}
}

Builder.build() 方法,通过已经配置好的成员变量,创建并返回一个 Retrofit 实例对象。至此,Retrofit 实例创建完毕,各项配置也已配置好,接下来通过创建网络请求接口实例,来分析 Retrofit 源码的创建过程。

3. Retrofit 创建网络请求接口实例

这里以最简单的获取用户信息为例,没有结合 RxJava 也没有任何的二次封装,越简单越容易理解。
首先,定义接收网络数据的用户信息类:

public class UserInfoBean implements Serializable {private String user_name;       // 用户名private String user_id;         // 用户ID......
}

接着,定义网络请求的接口类:

public interface Api {@GET(“api/userInfo”) // 获取用户信息Observable<UserInfoBean> getUserInfo(@Query("user_id") long user_id); // 请求网络数据的接口方法
}

注解 GET:表示使用 Get 方法发送网络请求,括号里面是网络请求的 URL 地址,Retrofit 把网络请求的 URL 分成了两部分:baseUrl 放在创建 Retrofit 对象时设置(参考前面 Retrofit 的构建);另一部分在网络请求接口设置(即这里)。

注意:如果接口里的 URL 是一个完整的网址,那么在创建 Retrofit 实例对象时设置的基地址 baseUrl 可以不设置。

返回值类型是:Observable,UserInfoBean 是解析得到的数据类型,如果不结合 RxJava 使用,则返回值类型是 Call。

最后,使用前面构建的 Retrofit 实例对象,创建接口类实例请求网络数据;

// 传入网络请求的接口类,通过 Retrofit.create() 方法创建网络请求接口的实例对象
Api serviceApi = retrofit.create(Api.class);
// 由网络请求接口实例对象,对发送请求的信息进行封装,生成最终的网络请求对象
Observable<UserInfoBean> userInfo = serviceApi.getUserInfo(user_id); 

3.1 Retrofit.create()

public final class Retrofit {final boolean validateEagerly;@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.public <T> T create(final Class<T> service) {Utils.validateServiceInterface(service);if (validateEagerly) { // 判断是否需要提前验证// eagerlyValidateMethods() 方法的作用是:// 1.给接口中每个方法的注解进行解析并得到一个 ServiceMethod 对象// 2.以 Method 为键将解析得到的对象存入 LinkedHashMap 集合中// 注意:如果不是提前验证则进行动态解析对应方法得到一个 ServiceMethod 对象,最后存入到LinkedHashMap集合中,类似延迟加载(默认)eagerlyValidateMethods(service);}// 创建网络请求接口的动态代理对象,即通过动态代理创建网络请求接口的实例并返回// 该动态代理是为了拿到网络请求接口实例上所有的注解// 该方法解读为:getProxyClass0(loader, interfaces).getConstructor(constructorParams)// .newInstance(new Object[]{InvocationHandler})return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },new InvocationHandler() { // 将代理类的实现交给 InvocationHandler 类作为具体的实现private final Platform platform = Platform.get();private final Object[] emptyArgs = new Object[0];// invoke() 方法,执行真正的逻辑(如再次转发给真正的实现类对象),还可以进行一些有用的操作// 如统计执行时间、进行初始化和清理、对接口调用进行检查等。@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)throws Throwable {// 如果该方法是 Object 中的方法,则正常调用即可if (method.getDeclaringClass() == Object.class) {return method.invoke(this, args);}if (platform.isDefaultMethod(method)) { // Android 平台没有重写该方法,因此不支持该操作return platform.invokeDefaultMethod(method, service, proxy, args);}// 由于是接口中的方法,不会走上面两个分支,流程转交给 Retrofit.loadServiceMethod() 方法进行处理// 获取到 ServiceMethod 实例对象后,调用 ServiceMethod.invoke() 方法return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);}});}// 该方法的主要作用是提前验证指定的方法是不是接口的默认方法,如果不是接口的默认方法,则遍历 service.getDeclaredMethods() // 方法获取到的方法数组,并对其中的每一个 Method 调用 loadServiceMethod() 方法private void eagerlyValidateMethods(Class<?> service) {Platform platform = Platform.get();for (Method method : service.getDeclaredMethods()) {// 检查指定的方法 method 是否是接口的默认方法if (!platform.isDefaultMethod(method)) {// 如果不是接口的默认方法,则遍历 service.getDeclaredMethods() 方法获取的方法数组// 对其中的每一个 Method 通过 loadServiceMethod() 方法加载并解析其注解loadServiceMethod(method);}}}
}

Retrofit.create() 方法首先判断是否需要提前验证接口中的方法,如果不需要,则通过动态代理创建网络请求接口的实例并返回,通过动态生成的代理类调用 interfaces 接口的方法。实际上是通过调用 InvocationHandler对象的 invoke() 方法来完成指定的功能。也就是当 Api 对象调用 getUserInfo() 接口方法时会进行拦截,调用会集中转发到 InvocationHandler.invoke() 方法进行集中处理,如:接口的统一配置,也就是注解的解析和网络请求参数的拼接。

在 InvocationHandler.invoke() 方法中,由于此时是接口中的方法,不会走上面两个判断分支,因此流程转交给 Retrofit.loadServiceMethod() 方法来获取网络请求接口方法的 ServiceMethod 实例对象,然后继续调用 ServiceMethod.invoke() 方法进行处理。

3.2 Retrofit.loadServiceMethod()

public final class Retrofit {private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();ServiceMethod<?> loadServiceMethod(Method method) {// 首先从 serviceMethodCache 缓存中获取方法对应的 ServiceMethodServiceMethod<?> result = serviceMethodCache.get(method);if (result != null) return result; // 如果不为null,则直接返回该 ServiceMethodsynchronized (serviceMethodCache) { // Map 集合中不存在,加锁进行处理,保证方法的唯一性result = serviceMethodCache.get(method); // 再一次进行获取if (result == null) { // 当前方法依旧不存在// 如果 serviceMethodCache 集合中没有找到对应的 ServiceMethod// 通过 ServiceMethod.parseAnnotations() 方法解析注解获取 ServiceMethodresult = ServiceMethod.parseAnnotations(this, method);// 将解析获取到的 ServiceMethod,以键值对<Method, ServiceMethod>存入 serviceMethodCache 集合中serviceMethodCache.put(method, result);}}return result;}
}

Retrofit.loadServiceMethod() 方法的主要作用是对接口中的指定方法的注解进行解析得到一个 ServiceMethod 对象,其内部通过 ServiceMethod.parseAnnotations() 方法来完成对指定的 Method 方法的注解进行解析,最后将解析获取到的 ServiceMethod,以键值对<Method, ServiceMethod>存入 serviceMethodCache 缓存集合中。

3.3 ServiceMethod.parseAnnotations()

abstract class ServiceMethod<T> {static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {// RequestFactory.parseAnnotations() 方法内部通过 Builder 建造者模式来构建 RequestFactory 实例对象// 对当前方法的所有信息进行解析:方法上的注解、方法参数注解、方法参数值等一系列的解析RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);// 获取 Method 方法的返回类型Type returnType = method.getGenericReturnType();if (Utils.hasUnresolvableType(returnType)) { // 判断返回类型是否是 T 或者 通配符类型throw methodError(method,"Method return type must not include a type variable or wildcard: %s", returnType);}if (returnType == void.class) { // 返回类型为空 throw methodError(method, "Service methods cannot return void.");}// 将新建的 RequestFactory 实例和 Retrofit、Method 实例一起转交给 HttpServiceMethod.parseAnnotations() 方法处理return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);}abstract T invoke(Object[] args);
}

ServiceMethod 是一个抽象类,既有实体方法也有抽象方法。在其实体方法 parseAnnotations() 中,首先通过 RequestFactory.parseAnnotations() 方法传入 Retrofit 实例和 Method 实例,构建一个 RequestFactory 实例对象,最后将新建的 RequestFactory 实例和 RetrofitMethod 实例一起转交给 HttpServiceMethod.parseAnnotations() 方法处理。

3.3.1 RequestFactory.parseAnnotations()
final class RequestFactory {static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {// 使用建造者模式来构建 RequestFactory 实例对象return new Builder(retrofit, method).build();}RequestFactory(Builder builder) {method = builder.method; // 网络请求方法baseUrl = builder.retrofit.baseUrl; // 请求基地址httpMethod = builder.httpMethod; // 请求方式,如:getrelativeUrl = builder.relativeUrl; // 请求相对路径 urlheaders = builder.headers; // 请求头数据contentType = builder.contentType; // 内容类型hasBody = builder.hasBody; // 是否有请求体isFormEncoded = builder.isFormEncoded; // 是否是表单提交isMultipart = builder.isMultipart; // 是否是表单提交(含有文件)parameterHandlers = builder.parameterHandlers; // 所有参数数据}......static final class Builder {final Retrofit retrofit; // retrofit 实例对象final Method method; // 当前网络请求接口方法 final Annotation[] methodAnnotations; // 获取当前网络请求方法注解集合 eg:@POSTfinal Annotation[][] parameterAnnotationsArray; // 当前网络请求方法传入参数的注解集合 eg (@Query("name") String name)final Type[] parameterTypes; // 当前网络请求方法传入参数类型集合 eg (String url) String.class @Nullable ParameterHandler<?>[] parameterHandlers;Builder(Retrofit retrofit, Method method) {this.retrofit = retrofit;this.method = method;this.methodAnnotations = method.getAnnotations();// 获取当前方法传入参数类型集合 eg (String url) String.class // 如果当前数据传入的参数有泛型类型的参数,这个方法可以返回泛型的完整信息 eg:(List<String> list) java.util.List<java.lang.String>// getParameterTypes(); 这个方法仅返回泛型信息 eg:(List<String> list) java.util.Listthis.parameterTypes = method.getGenericParameterTypes();// 获取当前网络请求方法传入参数的注解集合 eg (@Query("name") String name)this.parameterAnnotationsArray = method.getParameterAnnotations();}RequestFactory build() {for (Annotation annotation : methodAnnotations) { // 遍历网络请求方法上面的注解集合parseMethodAnnotation(annotation);  // 解析注解}if (httpMethod == null) { // 请求方式注解是否为nullthrow methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");}if (!hasBody) { // 是否有请求体,parseMethodAnnotation 由这个方法体现:DELETE、GET、OPTIONS、HEAD为 falseif (isMultipart) { // 没有请求体但是是表单提交(带有文件)throw methodError(method,"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");}if (isFormEncoded) { // 是否是表单提交throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "+ "request body (e.g., @POST).");}}int parameterCount = parameterAnnotationsArray.length; // 参数注解数组长度parameterHandlers = new ParameterHandler<?>[parameterCount]; // 创建ParameterHandler集合对象for (int p = 0; p < parameterCount; p++) {// 对参数注解进行逐一解析parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);}......// 实例化请求工厂对象return new RequestFactory(this);}}
}

RequestFactory.parseAnnotations() 方法内部通过 Builder 建造者模式来构建 RequestFactory 实例对象,通过对当前网络请求方法的所有信息进行解析:方法上的注解、方法参数注解、方法参数值等一系列的解析后保存起来。

3.4 HttpServiceMethod.parseAnnotations()

/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {// 检查接口方法上的注释,以构造一个可重复使用的 HTTP 服务方法// 由于要用到反射,开销较大,因此每个服务方法只构建一次然后重用它static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {// 通过 createCallAdapter() 方法创建 CallAdapter 实例对象CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);Type responseType = callAdapter.responseType(); // 获取响应数据类型 if (responseType == Response.class || responseType == okhttp3.Response.class) {throw methodError(method, "'"+ Utils.getRawType(responseType).getName()+ "' is not a valid response body type. Did you mean ResponseBody?");}// 请求方法是请求头 并且方法返回不为 Voidif (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {throw methodError(method, "HEAD method must use Void as response type.");}// 通过 createResponseConverter() 方法创建 Converter 实例对象用于解析服务端返回的数据Converter<ResponseBody, ResponseT> responseConverter =createResponseConverter(retrofit, method, responseType);// callFactory 就是开始初始化的 OkHttpClientokhttp3.Call.Factory callFactory = retrofit.callFactory;// 使用入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);}
}

HttpServiceMethod.parseAnnotations() 方法,首先通过 createCallAdapter() 方法创建 CallAdapter 实例对象,然后通过 createResponseConverter() 方法创建 Converter 实例对象用于解析服务端返回的数据,最后使用入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象。

3.4.1 HttpServiceMethod.createCallAdapter()
/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {......private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(Retrofit retrofit, Method method) {Type returnType = method.getGenericReturnType();    // 获取网络请求接口里方法的返回值类型Annotation[] annotations = method.getAnnotations(); // 获取网络请求接口里的注解,示例代码中是 @GETtry {// 根据获取的 returnType 和 annotations,通过 retrofit.callAdapter() 方法获取 CallAdapterreturn (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);} catch (RuntimeException e) { // Wide exception range because factories are user code.throw methodError(method, e, "Unable to create call adapter for %s", returnType);}}
}

HttpServiceMethod.createCallAdapter() 方法的主要作用是,根据获取的网络请求接口方法的返回值类型 returnTypeannotations 注解,通过 Retrofit.callAdapter() 方法从 Retrofit 对象中获取对应的网络请求适配器 CallAdapter 实例对象。

3.4.2 Retrofit.callAdapter()
public final class Retrofit {final List<CallAdapter.Factory> callAdapterFactories;// 从可用的 callAdapterFactories 工厂集合中返回指定 returnType 的 CallAdapter 实例对象// 构造 Retrofit 实例对象时进行添加的 CallAdapter.Factorypublic CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {// 继续调用 nextCallAdapter() 方法来获取 CallAdapter 实例对象return nextCallAdapter(null, returnType, annotations);}// 从可用的 callAdapterFactories 工厂集合中(skipPast 除外)返回指定 returnType 的 CallAdapter 实例对象public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,Annotation[] annotations) {checkNotNull(returnType, "returnType == null");checkNotNull(annotations, "annotations == null");int start = callAdapterFactories.indexOf(skipPast) + 1;for (int i = start, count = callAdapterFactories.size(); i < count; i++) {// 遍历 callAdapterFactories 集合寻找对应的工厂,进而再找出符合条件的 CallAdapter 并返回// 由于构造 Retroifit 实例对象时添加的是 RxJava2CallAdapterFactory,因此这里获取到的就是 RxJava2CallAdapterFactory 工厂// 由 RxJava2CallAdapterFactory.get()方法根据网络请求接口方法的返回值类型和注解,返回符合条件的 RxJava2CallAdapter 实例对象CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);if (adapter != null) {return adapter;}}// 如果最终没有找到工厂来提供需要的 CallAdapter,则拼接并抛出异常信息StringBuilder builder = new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");if (skipPast != null) {builder.append("  Skipped:");for (int i = 0; i < start; i++) {builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());}builder.append('\n');}builder.append("  Tried:");for (int i = start, count = callAdapterFactories.size(); i < count; i++) {builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());}throw new IllegalArgumentException(builder.toString());}
}

Retrofit.callAdapter() 方法将获取指定 returnTypeannotations 注解的 CallAdapter 实例对象的任务转交给 Retrofit.nextCallAdapter() 方法进行查找,找到符合条件的 CallAdapter 实例对象则直接返回,否者抛出报错信息。

3.4.3 HttpServiceMethod.createResponseConverter()
/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {......private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {Annotation[] annotations = method.getAnnotations();try {// 根据入参 responseType 及获取的 annotations,通过 retrofit.responseBodyConverter() 方法获取 Converterreturn retrofit.responseBodyConverter(responseType, annotations);} catch (RuntimeException e) { // Wide exception range because factories are user code.throw methodError(method, e, "Unable to create converter for %s", responseType);}}
}

HttpServiceMethod.createResponseConverter() 方法的主要作用是,根据入参 responseType 及获取的方法的 annotations 注解,通过 retrofit.responseBodyConverter() 方法从 Retrofit 对象中获取对应的数据转换器 Converter 实例对象。

3.4.4 Retrofit.responseBodyConverter()
public final class Retrofit {final List<Converter.Factory> converterFactories;// 从可用的 converterFactories 工厂集合中为 ResponseBody 找到指定 type 的 Converter 实例对象// 构造 Retrofit 实例对象时进行添加的 Converter.Factorypublic <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {return nextResponseBodyConverter(null, type, annotations);}// 从可用的 converterFactories 工厂集合中为 ResponseBody 找到指定 type 的 Converter 实例对象(除了 skipPast)public <T> Converter<ResponseBody, T> nextResponseBodyConverter(@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {checkNotNull(type, "type == null");checkNotNull(annotations, "annotations == null");int start = converterFactories.indexOf(skipPast) + 1;for (int i = start, count = converterFactories.size(); i < count; i++) {// 遍历 converterFactories 集合寻找对应的工厂,进而再找出符合条件的 Converter 并返回// 由于构造 Retroifit 实例对象时采用的是 Gson 解析方式,所以先取出的是 GsonConverterFactory 工厂// 由 GsonConverterFactory.responseBodyConverter()方法根据 responseType 类型和注解// 返回符合条件的 GsonResponseBodyConverter 实例对象Converter<ResponseBody, ?> converter =converterFactories.get(i).responseBodyConverter(type, annotations, this);if (converter != null) {//noinspection uncheckedreturn (Converter<ResponseBody, T>) converter;}}// 如果最终没有找到工厂来提供需要的 Converter,则拼接并抛出异常信息StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ").append(type).append(".\n");if (skipPast != null) {builder.append("  Skipped:");for (int i = 0; i < start; i++) {builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());}builder.append('\n');}builder.append("  Tried:");for (int i = start, count = converterFactories.size(); i < count; i++) {builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());}throw new IllegalArgumentException(builder.toString());}
}

Retrofit.responseBodyConverter() 方法将为 ResponseBody 获取指定 typeConverter 实例对象的任务转交给 Retrofit.nextResponseBodyConverter() 方法进行查找,找到符合条件的 Converter 实例对象则直接返回,否者抛出报错信息。

3.4.5 GsonConverterFactory.responseBodyConverter()
public final class GsonConverterFactory extends Converter.Factory {private final Gson gson;private GsonConverterFactory(Gson gson) {this.gson = gson;}@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,Retrofit retrofit) {// 根据目标类型,利用 Gson.getAdapter() 方法获取相应的 adapterTypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));// 使用创建 GsonConverterFactory 时保存的 gson 实例和 adapter 新建 GsonResponseBodyConverter 实例对象return new GsonResponseBodyConverter<>(gson, adapter);}
}

GsonConverterFactory.responseBodyConverter() 方法中根据目标类型,利用 Gson.getAdapter() 方法获取相应的 adapter,随后使用创建 GsonConverterFactory 时保存的 gson 实例和 adapter 新建 GsonResponseBodyConverter 实例对象。

3.4.6 GsonResponseBodyConverter
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {// 用于数据解析的主要类,内部采用工厂设计模式来实现不同 TypeAdapter 的创建,其成员变量fatories保存了// TypeAdapterFactory 列表,成员函数 getAdapter(type) 方法则根据不同的 type 去匹配 factories 中的一个工厂类,// 然后调用该工厂类的 create() 方法得到一个相应的 TypeAdapter 对象private final Gson gson;private final TypeAdapter<T> adapter;	 // TypeAdapter是一个抽象类,定义了转换的顶层接口,具体功能是在其子类中实现的GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {this.gson = gson;this.adapter = adapter;}@Override public T convert(ResponseBody value) throws IOException {// 通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入JsonReader jsonReader = gson.newJsonReader(value.charStream());try {// TypeAdapter.read() 方法将 Json 数据流解析成结构化对象T,其内部是通过 fromJson()方法T result = adapter.read(jsonReader);if (jsonReader.peek() != JsonToken.END_DOCUMENT) {throw new JsonIOException("JSON document was not fully consumed.");}return result;} finally {value.close();}}
}

GsonResponseBodyConverter 类实现了 Converter 接口,在其实现的 convert() 方法中,首先通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入,然后通过 TypeAdapter.read() 方法将 Json 数据流解析成结构化对象 T 并返回,其内部是通过 fromJson()方法实现的。

HttpServiceMethod.parseAnnotations() 方法的最后根据入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象并返回给代理对象 InvocationHandler.invoke() 方法最后调用的 Retrofit.loadServiceMethod() 方法,进而继续调用 HttpServiceMethod.invoke() 方法。

3.5 HttpServiceMethod

/** Adapts an invocation of an interface method into an HTTP call. */
// 将接口方法的调用适配为 HTTP 调用
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {......private final RequestFactory requestFactory;	 // 解析注解构造的请求工厂数据,里面有method,baseUrl,httpMethod等private final okhttp3.Call.Factory callFactory;	// 默认为 OkHttpClient 对象private final CallAdapter<ResponseT, ReturnT> callAdapter;   // 用于适配 OkHttpCall 的网络请求适配器private final Converter<ResponseBody, ResponseT> responseConverter;   // 用于解析响应的数据转换器 Converter // 构建 HttpServiceMethod 的实例对象,并保存入参到其成员变量中private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,CallAdapter<ResponseT, ReturnT> callAdapter,Converter<ResponseBody, ResponseT> responseConverter) {this.requestFactory = requestFactory;this.callFactory = callFactory;this.callAdapter = callAdapter;this.responseConverter = responseConverter;}@Override ReturnT invoke(Object[] args) {// 由前面的分析可知,这里调用的是 RxJava2CallAdapter.adapt() 方法,并新建 OkHttpCall 实例对象作为方法的入参return callAdapter.adapt(new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));}
}

HttpServiceMethod 是抽象类 ServiceMethod 的具体实现,用来存储一次网络请求的基本信息,比如:HostURL、请求方法等,还会存储用来适配 OkHttpCall 对象的 CallAdapter、用来创建网络请求 CallCall.Factory、用来进行数据解析的数据转换器 Converter 以及用来构建网络请求 RequestRequestFactory 等实例对象。

构建完 HttpServiceMethod 实例对象后,调用其 invoke() 方法并传入网络请求接口的参数,在其 invoke() 方法中首先将前面配置好的 RequestFactoryCall.FactoryConverter 以及输入的网络请求接口的参数构建 OkHttpCall 实例对象,然后将构建的 OkHttpCall 实例对象作为入参传给 RxJava2CallAdapter.adapt() 方法进行下一步的处理。

3.6 OkHttpCall

final class OkHttpCall<T> implements Call<T> {private final RequestFactory requestFactory;private final Object[] args;private final okhttp3.Call.Factory callFactory;private final Converter<ResponseBody, T> responseConverter;OkHttpCall(RequestFactory requestFactory, Object[] args,okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {this.requestFactory = requestFactory;    // 网络请求 RequestFactory 工厂 this.args = args;    // 网络请求接口的参数this.callFactory = callFactory;	   // 网络请求 Call 工厂this.responseConverter = responseConverter;	   // 数据转换器}
}

OkHttpCallRetrofit 库中接口 Call 的一个实现类,其入参就是前面配置好的网络请求会用到的一些资源,实现了接口 Call 的几个重要方法:

  • execute():表示同步请求,返回值就是网络请求结果;
  • enqueue(Callback<T> callback):表示异步请求,返回值需要通过 Callback 回调来获取;
  • request():表示创建一个请求,返回 Request 类型。

3.7 RxJava2CallAdapter.adapt()

final class RxJava2CallAdapter implements CallAdapter<Object> {private final Type responseType;@Override public Type responseType() {return responseType;}@Override public <R> Object adapt(Call<R> call) {// 使用入参 OkHttpCall 对象构建 CallObservable 实例对象,后续根据不同的条件新建或转换为符合要求的 ObservableObservable<Response<R>> responseObservable = new CallObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) { // 参考 2.6.1 RxJava2CallAdapterFactory.create()的分析,isBody 为 trueobservable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) { // 如果设置了 scheduler 则需建立订阅关系observable = observable.subscribeOn(scheduler);}// Flowable 能够发射0或n个数据,并以成功或者错误事件终止。支持背压,可以控制数据源发射的速度if (isFlowable) { // 如果是 Flowable,则将 Observable 转换为 Flowablereturn observable.toFlowable(BackpressureStrategy.LATEST);}if (isSingle) { // 如果是 Single,则将 Observable 转换为 Single,Single 只发射单个数据或者错误事件return observable.singleOrError();}// Maybe 能够发射0或者1个数据,要么成功,要么失败。有点类似于 Optionalif (isMaybe) { // 如果是 Maybe,则将 Observable 转换为 Maybereturn observable.singleElement();}// Completable 从来不发射数据,只处理onComplete和onError事件。可以看成 Rx 的 Runnableif (isCompletable) { // 如果是 Completable,则将 Observable 转换为 Completablereturn observable.ignoreElements();}return observable;}
}

RxJava2CallAdapter.adapt() 方法经过判断处理得到所需的可以操作的 Observable 网络请求对象,由于这里只是简单的使用,没有特殊要求的情况下返回的是 BodyObservable 对象。

问题:为什么 InvocationHandler.invoke() 方法不可以直接返回 OKHttpCall 对象,而是调用 CallAdapter.adapt(call, args) 方法进行适配器适配?
答:想象一下,如果没有适配器的话,网络请求返回接口只能直接返回 OkHttpCall,且所有的网络请求都是用 OkHttpCall 进行,这样就失去了 Retrofit 封装的意义,也不够灵活,如:RxJavaObservable 就无法支持。而采用适配器模式,将网络请求的核心类 OkHttpCall 进行适配,可根据实际需要通过适配器的适配返回适配后的对象,使得用户在使用 Retrofit 的时候可以自定义想要的返回类型。

小结

Retrofit 采用了外观模式统一调用创建网络请求接口实例和网络请求参数配置的方法,具体细节是:

  • 通过动态代理模式来动态的创建网络请求接口的实例对象 HttpServiceMethod
  • 通过 Retrofit.loadServiceMethod() 方法从 serviceMethodCache 缓存队列中获取 HttpServiceMethod 实例对象,如缓存中已有对应的实例对象,则直接返回(缓存机制,避免重复解析创建);
  • 如果缓存中没有则由 ServiceMethod.parseAnnotations() 解析注解获得,通过解析网络请求接口方法的参数、返回值类型和注解,从 Retrofit 对象中获取对应的网络请求的 URL 地址、网络请求执行器、网络请求适配器及数据转换器(策略模式);
  • 构建 HttpServiceMethod 实例对象,保存前面解析获取到的网络请求所需的必要信息,并把新建的 HttpServiceMethod 实例对象添加到 serviceMethodCache 缓存队列中;
  • 调用 HttpServiceMethod.invoke() 方法,通过适配的 RxJava2CallAdapter.adapt() 方法,传入新建的 OkHttpCall 实例对象,最终创建并返回一个 Observable 类型的网络请求对象 BodyObservable

4. Retrofit 执行网络请求

经过前面几节的分析,Retrofit 实例对象和 Observable 类型的网络请求对象都已创建完,那怎么来执行网络请求呢?

接下来为了更好的理解 Retrofit 的网络请求执行流程,对 Retrofit 进行了简单的封装以便于更好的理解其与 RxJava 的结合使用,示例代码如下:

RetrofitManager.getInstance()	// 获取 Retrofit 实例对象.getNetService(Api.class)	// 内部通过 Retrofit.create() 方法创建网络请求接口的实例对象.getUserInfo()	// 通过网络请求接口的实例对象,对请求的参数等信息进行封装,生成最终的网络请求对象 Observable<UserInfoBean>.subscribeOn(Schedulers.io())	// 指定被观察者 Observable 是在 Schedulers.io() 线程执行操作.observeOn(AndroidSchedulers.mainThread()) // 指定观察者 Observer在 AndroidSchedulers.mainThread(),即 Android主线程上执行操作,以更新UI.subscribe(new Observer<UserInfoBean>() { // 构建观察者 Observer 实例对象,通过 subscribe() 完成订阅,此时被观察者 Observable 开始向观察者发送数据@Overridepublic void onSubscribe(Disposable d) { // 订阅时的操作 }@Overridepublic void onNext(UserInfoBean userInfo) {// UI界面展示获取到的用户信息}@Overridepublic void onError(Throwable e) { // 出错时的操作 }@Overridepublic void onComplete() { // 完成时的操作 }});

被观察者 Observable 和观察者 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer

4.1 Observable.subscribe()

public abstract class Observable<T> implements ObservableSource<T> {@SchedulerSupport(SchedulerSupport.NONE)@Overridepublic final void subscribe(Observer<? super T> observer) {ObjectHelper.requireNonNull(observer, "observer is null");try {// RxJava 提供的一个钩子方法,用于在 Observable 被订阅时进行一些自定义的逻辑处理// 你可以通过实现该方法来拦截所有的 subscribe 调用,并对其进行相应的处理observer = RxJavaPlugins.onSubscribe(this, observer);ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");// 继续调用 subscribeActual()subscribeActual(observer);} catch (NullPointerException e) { // NOPMDthrow e;} catch (Throwable e) {Exceptions.throwIfFatal(e);// can't call onError because no way to know if a Disposable has been set or not// can't call onSubscribe because the call might have set a Subscription alreadyRxJavaPlugins.onError(e);NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");npe.initCause(e);throw npe;}}
}

Observable.subscribe() 方法中继续调用其 subscribeActual() 方法,看名字应该是真正用来订阅的,但其实这是一个抽象方法,在前面获取到的 BodyObservable 继承自 Observable 并实现了该方法。

4.2 BodyObservable.subscribeActual()

final class BodyObservable<T> extends Observable<T> {private final Observable<Response<T>> upstream;// 创建 BodyObservable 时传入的是 CallObservable 实例对象BodyObservable(Observable<Response<T>> upstream) {this.upstream = upstream;}@Override protected void subscribeActual(Observer<? super T> observer) {// 这里转调 CallObservable.subscribe() 方法upstream.subscribe(new BodyObserver<>(observer));}

BodyObservable.subscribeActual() 方法继续转调 CallObservable.subscribe() 方法,CallObservable 本身没有 subscribe() 方法,因此调用的是其父类 Observable.subscribe() 方法,最后流程转调到 CallObservable.subscribeActual() 方法。

4.3 CallObservable.subscribeActual()

final class CallObservable<T> extends Observable<Response<T>> {private final Call<T> originalCall;CallObservable(Call<T> originalCall) {this.originalCall = originalCall;}@Override protected void subscribeActual(Observer<? super Response<T>> observer) {// 为每个新的观察者克隆 originalCall 的副本Call<T> call = originalCall.clone();observer.onSubscribe(new CallDisposable(call)); // 开始执行onSubscribe方法boolean terminated = false;try {// 请求开始执行,会进行阻塞Response<T> response = call.execute();if (!call.isCanceled()) { // 请求未被取消,拿到数据之后,执行onNext()方法发送数据observer.onNext(response);}if (!call.isCanceled()) { // 未被取消,则执行完成terminated = true;observer.onComplete();}} catch (Throwable t) {Exceptions.throwIfFatal(t);if (terminated) { RxJavaPlugins.onError(t); // 执行异常方法} else if (!call.isCanceled()) {try {observer.onError(t);} catch (Throwable inner) {Exceptions.throwIfFatal(inner);RxJavaPlugins.onError(new CompositeException(t, inner));}}}}
}

CallObservable.subscribeActual() 方法的执行流程如下:

  • 通过 call.execute() 方法执行请求,此处 Call 是在执行 RxJava2CallAdapter.adapt() 方法时传进来的。因此这里调用的是 Call 的实现类 OkHttpCall.execute() 方法;
  • 请求未取消,且成功拿到数据之后,执行 Observer.onNext() 方法向观察者发送数据,即 UI 界面获取到数据并展示获取到的信息。

4.4 OkHttpCall.execute()

final class OkHttpCall<T> implements Call<T> {@GuardedBy("this")private @Nullable okhttp3.Call rawCall;@GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.private @Nullable Throwable creationFailure;@GuardedBy("this")private boolean executed;@Override public Response<T> execute() throws IOException {okhttp3.Call call;synchronized (this) { // 加锁处理,防止重复执行当前请求if (executed) throw new IllegalStateException("Already executed.");executed = true;if (creationFailure != null) { // 创建 RealCall 失败,出现了异常,进行处理if (creationFailure instanceof IOException) {throw (IOException) creationFailure;} else if (creationFailure instanceof RuntimeException) {throw (RuntimeException) creationFailure;} else {throw (Error) creationFailure;}}call = rawCall;if (call == null) { // 第一次执行时为nulltry {call = rawCall = createRawCall(); // 创建一个 RealCall} catch (IOException | RuntimeException | Error e) {throwIfFatal(e); //  Do not assign a fatal error to creationFailure.creationFailure = e;throw e;}}}if (canceled) {call.cancel();}// 执行网络请求并解析响应return parseResponse(call.execute());}private okhttp3.Call createRawCall() throws IOException {// 这里 callFactory 就是之前 Retrofit 初始化时添加的 OkHttpClientokhttp3.Call call = callFactory.newCall(requestFactory.create(args));if (call == null) {throw new NullPointerException("Call.Factory returned null.");}return call;}
}

OkHttpCall.execute() 方法中,首先调用 createRawCall() 方法创建一个 RealCall,随后调用 RealCall.execute() 方法执行网络请求,最后调用 parseResponse() 方法解析网络请求响应。

4.4.1 RequestFactory.create()
final class RequestFactory {private final ParameterHandler<?>[] parameterHandlers;......okhttp3.Request create(Object[] args) throws IOException {@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;int argumentCount = args.length;if (argumentCount != handlers.length) {throw new IllegalArgumentException("Argument count (" + argumentCount+ ") doesn't match expected count (" + handlers.length + ")");}// 使用构建 RequestFactory 实例时保存的网络请求所需的必要参数来构建 RequestBuilder 实例对象RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,headers, contentType, hasBody, isFormEncoded, isMultipart);// 对网络请求接口方法中的每个参数利用对应的 ParameterHandler 进行解析List<Object> argumentList = new ArrayList<>(argumentCount);for (int p = 0; p < argumentCount; p++) {argumentList.add(args[p]);handlers[p].apply(requestBuilder, args[p]);}// 最后通过 RequestBuilder 建造者模式构建 Request 实例对象return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();}
}

RequestFactory.create() 方法首先使用构建 RequestFactory 实例时保存的网络请求所需的必要参数来构建 RequestBuilder 实例对象,随后通过 RequestBuilder 建造者模式构建 Request 实例对象。

4.4.2 OkHttpClient.newCall()
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {......public Call newCall(Request request) {return RealCall.newRealCall(this, request, false);}
}

OkHttpClient.newCall() 方法继续调用 RealCall.newRealCall() 方法创建 RealCall 实例对象并返回。

4.4.3 RealCall.newRealCall()
final class RealCall implements Call {final OkHttpClient client;private Transmitter transmitter;final Request originalRequest;final boolean forWebSocket;private boolean executed;private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {this.client = client;this.originalRequest = originalRequest;this.forWebSocket = forWebSocket;}static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {RealCall call = new RealCall(client, originalRequest, forWebSocket);call.transmitter = new Transmitter(client, call);return call;}
}

RealCallOkHttp 库中 Call 的实现类,实现了 Call 接口内部定义的同步与异步请求、取消请求等方法。在 RealCall.newRealCall() 方法中,首先根据入参创建 RealCall 实例对象,然后使用新建的 RealCallOkHttpClient 自身来新建 Transmitter 实例对象并赋值给 RealCall.transmitter 成员变量,最后返回刚创建的 RealCall 实例对象。

OkHttp 后面的代码本文不再深入,后续写文章深入剖析,现在已经获取到 RealCall 实例对象,并调用 RealCall.execute() 方法,后续会通过 RealCall 的拦截器链层层调用后,再一步步返回请求响应 Response,也就是说现在已经获取到网络请求返回的 Response,接下来分析 Retrofit 是如何解析请求响应的。

4.5 OkHttpCall.parseResponse()

final class OkHttpCall<T> implements Call<T> {Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {ResponseBody rawBody = rawResponse.body(); // 拿到返回过来的响应体// Remove the body's source (the only stateful object) so we can pass the response along.// 移除 Response 的响应体 ResponseBody(唯一有状态的对象),这样我们就可以传递响应rawResponse = rawResponse.newBuilder()// Response 设置没有内容的 NoContentResponseBody.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();int code = rawResponse.code(); // 响应码if (code < 200 || code >= 300) { // 响应异常情况try {// 缓冲整个主体以避免将来的 I/O 操作ResponseBody bufferedBody = Utils.buffer(rawBody);return Response.error(bufferedBody, rawResponse); // 将请求异常的情况进行返回} finally {rawBody.close();}}if (code == 204 || code == 205) { // 请求成功情况,只是返回数据为nullrawBody.close();return Response.success(null, rawResponse);}ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);try {// 转换器 Converter 转换 Response 的 ResponseBodyT body = responseConverter.convert(catchingBody);// 调用 Response.success() 方法构建一个新的 Response 并返回 return Response.success(body, rawResponse);} catch (RuntimeException e) {// If the underlying source threw an exception, propagate that rather than indicating it was// a runtime exception.catchingBody.throwIfCaught();throw e;}}
}

OkHttpCall.parseResponse() 方法首先获取 ResponseResponseBody 响应体,调用 responseConverter.convert() 方法对 ResponseBody 响应体进行数据转换,最后调用 Response.success() 方法构建一个新的 Response 并返回。

4.5.1 GsonResponseBodyConverter.convert()
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {// 用于数据解析的主要类,内部采用工厂设计模式来实现不同 TypeAdapter 的创建,其成员变量fatories保存了// TypeAdapterFactory 列表,成员函数 getAdapter(type) 方法则根据不同的 type 去匹配 factories 中的一个工厂类,// 然后调用该工厂类的 create() 方法得到一个相应的 TypeAdapter 对象private final Gson gson;private final TypeAdapter<T> adapter;	 // TypeAdapter是一个抽象类,定义了转换的顶层接口,具体功能是在其子类中实现的GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {this.gson = gson;this.adapter = adapter;}@Override public T convert(ResponseBody value) throws IOException {// 通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入JsonReader jsonReader = gson.newJsonReader(value.charStream());try {// TypeAdapter.read() 方法将 Json 数据流解析成结构化对象T,其内部是通过 fromJson()方法// 此处 adapter 是 GsonConverterFactory.responseBodyConverter() 方法中由 Gson.getAdapter()方法获取的T result = adapter.read(jsonReader);if (jsonReader.peek() != JsonToken.END_DOCUMENT) {throw new JsonIOException("JSON document was not fully consumed.");}return result;} finally {value.close();}}
}

GsonResponseBodyConverter 类在前面分析过,在其实现的 convert() 方法中,首先通过 gson.newJsonReader() 方法新建 JsonReader 实例对象,将服务端返回的 Json 数据以流的形式读入,然后通过 TypeAdapter.read() 方法将 Json 数据流解析成结构化对象 T 并返回,其内部是通过 fromJson()方法实现的。

4.5.2 Gson.getAdapter()
public final class Gson {@SuppressWarnings("unchecked")public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {// 获取 Map<TypeToken<?>, TypeAdapter<?>> 缓存中的请求 adapter 是否存在,存在即返回 TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);if (cached != null) {return (TypeAdapter<T>) cached;}// 本地线程缓冲中获取当前线程的请求数据信息Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();boolean requiresThreadLocalCleanup = false; // 是否清除本地线程缓冲数据if (threadCalls == null) { // 本地线程缓冲中不存在threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>(); // 实例化一个 HashMapcalls.set(threadCalls); // 缓存至 TLB 中requiresThreadLocalCleanup = true; // 进行清除}// 键和值类型参数始终一致FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type); // 获取当前返回类型的FutureTypeAdapter适配器if (ongoingCall != null) {// 已经存在当前返回值的适配器则直接返回return ongoingCall;}try { // 当前 FutureTypeAdapter 适配器依旧为null,创建一个适配器FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();threadCalls.put(type, call); // 并将当前适配器与对应的 type 保存到 HashMap 中// 在 Gson 初始化的 List<TypeAdapterFactory> 中遍历查找对应的 TypeAdapterfor (TypeAdapterFactory factory : factories) {// 获取到解析适配器TypeAdapter<T> candidate = factory.create(this, type);if (candidate != null) {call.setDelegate(candidate); // 设置参数typeTokenCache.put(type, candidate); // 存入缓存 Map<TypeToken<?>, TypeAdapter<?>> 集合中return candidate;}}throw new IllegalArgumentException("GSON cannot handle " + type);} finally {threadCalls.remove(type);if (requiresThreadLocalCleanup) {calls.remove();}}}
}

Gson.getAdapter() 方法查找并获取指定类型映射的 TypeAdapter 实例对象,TypeAdapter 是一个抽象类,其 read() 方法在不同子类中实现的方式也不一样,这里以 ReflectiveTypeAdapterFactory 类的内部类 Adapter 为例,其继承自 TypeAdapter 类并实现其 read() 方法。

4.5.3 ReflectiveTypeAdapterFactory.Adapter.read()
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {......public static final class Adapter<T> extends TypeAdapter<T> {private final ObjectConstructor<T> constructor;private final Map<String, BoundField> boundFields;@Override public T read(JsonReader in) throws IOException {if (in.peek() == JsonToken.NULL) { // 得到 JsonToken.NULL 则不进入当前判断in.nextNull();return null;}T instance = constructor.construct(); // 初始化实例操作try {in.beginObject(); // 开始解析对象while (in.hasNext()) { // 是否有下一个,第一次到这里,返回 PEEKED_DOUBLE_QUOTED_NAME trueString name = in.nextName();  // 获取 name 信息BoundField field = boundFields.get(name);  // 根据集合去获取里面的字段信息if (field == null || !field.deserialized) { // 如果字段为 null 或字段不能反序列化in.skipValue(); // 跳过value值,因为解析的类对象中不存在当前字段或者这个字段不能反序列化} else {field.read(in, instance); // 开始执行,根据字段类型去读取 value 值}}} catch (IllegalStateException e) {throw new JsonSyntaxException(e);} catch (IllegalAccessException e) {throw new AssertionError(e);}in.endObject();return instance;}}
}

限于篇幅 Retrofit 后续解析过程本文不再继续深入,在通过数据转换器 GsonResponseBodyConverter.convert() 方法对 ResponseBody 响应体进行数据解析转换后,最后会调用 Response.success() 方法构建一个新的 Response 并返回。

4.6 Response.success()

public final class Response<T> {// 由 rawResponse 和 body 创建一个成功的 Response 作为反序列化的 bodypublic static <T> Response<T> success(@Nullable T body, okhttp3.Response rawResponse) {checkNotNull(rawResponse, "rawResponse == null");if (!rawResponse.isSuccessful()) {throw new IllegalArgumentException("rawResponse must be successful response");}// 判空并检查是成功的,则重新构建 okhttp3.Response 响应return new Response<>(rawResponse, body, null);}
}

Response.success() 方法中,由 rawResponsebody 创建一个成功的 Response 响应作为反序列化的 body 并返回。

此时,回到 4.3 CallObservable.subscribeActual() 方法,如果请求未取消,且成功拿到数据之后,执行 Observer.onNext() 方法向观察者发送数据,即 UI 界面获取到数据并展示获取到的信息。流程至此,Retrofit 的请求及解析过程也剖析完毕,当然里面还有很多细节,在一篇文章中是很难剖析完全的,感兴趣的可以再深入跟一下,后续有时间,笔者也会继续剖析。

小结

Retrofit 结合 RxJava 来实现网络请求是目前比较常见的异步编程模式,可以提高网络请求的效率和响应速度。

  • Retrofit 创建 Observable 网络请求对象后,使用该对象发送网络请求的结果;
  • Retrofit 使用 OkHttpRequest 发送网络请求,网络请求最终是通过 OkHttp 内部的 RealCall 来执行,经过其拦截器链层层调用后,再一步步返回请求响应 Response
  • Retrofit 对返回的数据使用创建 Retrofit 实例时设置的数据转换器工厂 GsonConverterFactory 所构建的 GsonResponseBodyConverter 解析返回的数据,最终得到一个 Response 对象;
  • 通过 RxJava 的 subscribe() 方法为 Observable 订阅观察者 Observer,接收并处理网络请求的返回值;
  • 通过 RxJava 提供的线程调度器,可以方便的切换线程,实现在不同的线程中执行网络请求和 UI 操作。

总结

Retrofit 本质上是一个 RESTfulHttp 网络请求框架的封装,通过大量的设计模式封装了 OkHttp,使得网络请求更加简洁易用。

  • 创建 Retrofit 实例,通过 Retrofit 内部类 Builder 构建实例对象,并配置网络请求所需的各种参数及适配器工厂等;
  • 创建网络请求接口的实例,RetrofitHttp 请求抽象成 Java 接口,在接口里用注解描述和配置网络请求参数;
  • Retrofit 采用外观模式统一调用创建网络请求接口实例和网络请求参数配置的方法:
    • 动态创建网络请求接口的实例(通过 InvocationHandler 对象的 invoke() 方法统一进行拦截处理);
    • 创建 ServiceMethod 对象,并对 ServiceMethod 对象进行网络请求参数配置:网络请求接口方法的参数、返回值和注解等;
    • 创建并返回 OkHttpCall 类型的网络请求对象,然后通过适配的 RxJava2CallAdapter.adapt() 方法,返回适配后的 Observable 类型的网络请求对象 BodyObservable
  • Retrofit 使用 OkHttpRequest 发送网络请求,网络请求最终是通过 OkHttp 内部的 RealCall 来执行,经过其拦截器链层层调用后,再一步步返回请求响应 Response
  • Retrofit 对返回的数据使用创建 Retrofit 实例时设置的数据转换器工厂 GsonConverterFactory 所构建的 GsonResponseBodyConverter 解析返回的数据,最终得到一个 Response 对象;
  • 通过 RxJava 的 subscribe() 方法为 Observable 订阅观察者 Observer,接收并处理网络请求的返回值;
  • 最后,通过 RxJava 提供的线程调度器,可以方便的切换线程,实现在不同的线程中执行网络请求和 UI 操作。

参考

  • square/Retrofit:github.com/square/retrofit
  • square/okhttp:github.com/square/okhttp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/362815.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenAI穿着「皇帝的新衣」;扒了数万条帖子汇总100种AIGC玩法;北美出海的财务避坑指南;我创业「如」有CTO | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; 1. 我扒了 Reddit 论坛数万条帖子&#xff0c;汇总了 GenAI 的 100 种玩法 ChatGPT 已经问世一年半了。这期间诞生了很多大语言模型和生成式人工智能…

备份和还原

stai和dnta snat&#xff1a;源地址转换 内网---外网 内网ip转换成可以访问外网的ip 内网的多个主机可以使用一个有效的公网ip地址访问外部网络 DNAT&#xff1a;目的地址转发 外部用户&#xff0c;可以通过一个公网地址访问服务内部的私网服务。 私网的ip和公网ip做一个…

【JavaEE进阶】Spring AOP使用篇

目录 1.AOP概述 2.SpringAOP快速入门 2.1 引入AOP依赖 2.2 编写AOP程序 3. Spring AOP详解 3.1 Spring AOP 核心概念 3.1.1切点(Pointcut) 3.1.2 连接点 (Join Point) 3.1.3 通知(Advice) 3.1.4 切面(Aspect) 3.2 通知类型 3.3PointCut 3.4 切面优先级 3.5 切点表…

「51媒体」政企活动媒体宣发如何做?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 政企活动媒体宣发是一个系统性的过程&#xff0c;需要明确…

使用Scala爬取安居客房产信息并存入CSV文件

使用Scala爬取安居客房产信息并存入CSV文件 本篇博客中&#xff0c;我们将介绍如何使用Scala语言编写一个简单的程序&#xff0c;来爬取安居客&#xff08;Anjuke&#xff09;网站上的房产信息&#xff0c;并将这些信息存储到CSV文件中。这个示例将涵盖HTTP请求、HTML解析、数…

麒麟系统安装MySQL

搞了一整天&#xff0c;终于搞定了&#xff0c;记录一下。 一、背景 项目的原因&#xff0c;基于JeecgBoot开发的系统需要国产化支持&#xff0c;这就需要在电脑上安装MySQL等支撑软件。 国产化项目的操作系统多是麒麟系统&#xff0c;我的系统如下&#xff1a; arm64架构。…

详细分析Oracle修改默认的时间格式(四种方式)

目录 前言1. 会话级别2. 系统级别3. 环境配置4. 函数格式化5. 总结 前言 默认的日期和时间格式由参数NLS_DATE_FORMAT控制 如果需要修改默认的时间格式&#xff0c;可以通过修改会话级别或系统级别的参数来实现 1. 会话级别 在当前会话中设置日期格式&#xff0c;这只会影响…

CCSP自考攻略+经验总结

备考攻略 备考攻略准备阶段通读阶段精度阶段总复习阶段刷题阶段命运审判 写到最后 备考攻略 趁着对ssp知识点的理解还在&#xff0c;开始ccsp的考证之路&#xff0c;文章结构还是按照cissp备考篇的结构梳理。本次备考和cissp的离职在家备考不同&#xff0c;ccsp是在职利用非工…

2018年全国大学生数学建模竞赛A题高温服装设计(含word论文和源代码资源)

文章目录 一、部分题目二、部分论文三、部分Matlab源代码问题11 求解h1h22 已知h1h2求解温度分布 问题21 求解第二层最佳厚度 四、完整word版论文和源代码&#xff08;两种获取方式&#xff09; 一、部分题目 2018 年高教社杯全国大学生数学建模竞赛题目 A 题 高温作业专用服…

【C语言】字符/字符串+内存函数

目录 Ⅰ、字符函数和字符串函数 1 .strlen 2.strcpy 3.strcat 4.strcmp 5.strncpy 6.strncat 7.strncmp 8.strstr 9.strtok 10.strerror 11.字符函数 12. 字符转换函数 Ⅱ、内存函数 1 .memcpy 2.memmove 3.memcmp 4.memset Ⅰ、字符函数和字符串函数 1 .strlen 函数原型&…

Vite: 关于Rollup打包

概述 Rollup 是一款基于 ES Module 模块规范实现的 JavaScript 打包工具&#xff0c;在前端社区中赫赫有名&#xff0c;同时也在 Vite 的架构体系中发挥着重要作用不仅是 Vite 生产环境下的打包工具&#xff0c;其插件机制也被 Vite 所兼容&#xff0c;可以说是 Vite 的构建基…

JavaScript--js基础(详细 全面)

目录 前言: JavaScript 是什么&#xff1f;JavaScript 简介 1.JavaScript历史 2.JavaScript 具有以下特点 第一个JavaScript程序 1.在脚本文件中编写JavaScript代码 2.JavaScript代码执行顺序 基本语法 1.变量 2.数据类型 3.算术运算符 4.赋值运算 5.字符串运算符 6…

微服务应用与开发知识点练习【Gateway,OpenFeign,Dubbo,RocketMQ和RabbitMQ,JPA,Redis,Mycat】

一、选择题 【Gateway】 1.Spring Cloud Gateway与Nacos整合实现负载均衡时&#xff0c;路由配置中的URI前缀应该是&#xff1f;&#xff08;A &#xff09; A. lb:// B. nacos:// C. http:// D. discovery:// Spring Cloud Gateway与Nacos整合实现负载均衡时&#xff0c…

华为od 2024 | 什么是华为od,od 薪资待遇,od机试题清单

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、队列4、链表5、栈6、滑动窗口7、二叉树8、并查集9、矩阵 三、算法1、基础算法① 贪心思维② 二分查…

鸿蒙面试心得

自疫情过后&#xff0c;java和web前端都进入了冰河时代。年龄、薪资、学历都成了找工作路上躲不开的门槛。 年龄太大pass 薪资要高了pass 学历大专pass 好多好多pass 找工作的路上明明阳关普照&#xff0c;却有一种凄凄惨惨戚戚说不清道不明的“优雅”意境。 如何破局&am…

vite-ts-cesium项目集成mars3d修改相关的包和配置参考

如果vite技术栈下使用原生cesium&#xff0c;请参考下面文件的包和配置修改&#xff0c;想用原生创建的viewer结合我们mars3d的功能的话。 1. package.json文件 "dependencies": {"cesium": "^1.103.0","mars3d": "^3.7.18&quo…

Java——IO流(一)-(8/8):释放资源-try-catch-finally、try-catch-resource

目录 try-catch-finally 介绍 实例演示1 实例演示2 try-catch-resource 介绍 实例演示 try-catch-finally 介绍 普通的释放流的方法可能会因中间的异常或是其他原因&#xff0c;导致程序执行不到释放流的代码就结束了&#xff0c;会有资源浪费的风险&#xff0c;所以建…

Web渗透:文件包含漏洞(part.1)

"文件包含漏洞"&#xff08;File Inclusion Vulnerability&#xff09;是一种常见的Web应用程序漏洞&#xff0c;攻击者可以通过这个漏洞在目标系统上包含或执行任意文件。主要有两种类型的文件包含漏洞&#xff1a; 本地文件包含&#xff08;Local File Inclusion, …

Python学习打卡:day17

day17 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day17121、Python 操作 MySQL 基础使用pymysql创建到 MySQL 的数据库链接执行 SQL 语句执行非查询性质的SQL语句执行查询性质的SQL语句 122、Pyth…

全局mixins

一、文章由来 在开发过程中发现在钩子函数位置直接使用dicts就能直接绑定数据了&#xff0c;由此溯源发现了自己的盲区 二、局部使用 // myMixin.js文件 var myMixin {created: function () {this.hello()},methods: {hello: function () {console.log(hello from mixin!)…