赞
踩
在 Android 开发中,通过网络请求获取服务端数据是一项基本且常见的需求。目前有多种网络请求框架可供选择,其中 Android-Async-Http、Volley、OkHttp 和 Retrofit 是较为流行的、开源的网络请求框架。如何选择它们?孰优孰劣?仁者见仁智者见智,我个人觉得适合的就是最好的,不要盲目跟风去更换掉之前选用的网络请求框架,毕竟老代码那是牵一发而动全身哈!对于新项目来说,选择一个好用的网络请求框架,还是很有必要的,而 Retrofit 作为当下最火的一个网络开源请求库,还是值得学习并尝试使用的。
Retrofit 是一个在 Android 开发中常用的网络请求框架。是 Square 公司基于他们自己的另一个比较火的网络库 OkHttp,进行封装的一个 RESTful 的 HTTP 网络请求框架。其提供了简洁而强大的 API,用于与 RESTful 服务进行通信。
Retrofit 的一些主要特点和优势:
Retrofit 与其它主流网络请求库之间的功能与区别:
结合上图,解释一下 Retrofit 网络请求过程:
本文不准备详细介绍 Retrofit 的使用,主要是深入源码剖析其原理,下面就根据上面的请求过程,逐步剖析 Retrofit 的源码调用过程,注意:后续的源码基于 Retrofit 2.5.0 版本进行分析。
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();
public final class Retrofit { // 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象) // 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等 private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); // 网络请求执行器的工厂,其作用是生产网络请求执行器 Call,Retrofit 默认使用 OkHttp final 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 实例对象,并配置好类里面的各成员变量。
工厂模式:设计模式中工厂模式,是将”类实例化的操作”与“使用对象的操作”分开,使得使用者不用知道具体参数就可以实例化出所需要的“产品”类。
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 类的成员变量进行赋值。
建造者模式:将一个复杂对象的构建与表示分离,使得用户在不知道对象的创建细节情况下就可以直接创建复杂的对象。
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 8 Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); } }
由 Platform.get() 方法可以看出,Retrofit 2.5 目前支持 Android 和 Java 平台,翻看之前 2.0 版本的代码,那会儿还支持 iOS 平台。在方法中通过判断返回对应平台的实例对象,这里返回的是 Android 的实例对象,即指定了运行平台为 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 来新建一个 Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { // 通过上面新建的 Handler 发送消息,将消息发送到UI主线程,在UI线程对网络请求返回数据进行处理 handler.post(r); } } } }
至此,Retrofit 的 Builder 类介绍完毕,通过跟踪查看代码可知,在 Builder 类中设置了默认的平台类型对象:Android、网络请求适配器工厂:CallAdapterFactory(CallAdapter 用于对原始 Call 进行再次封装,如结合 RxJava 使用时将 Call 封装成 Observable)、数据转换器工厂:ConverterFactory 和回调执行器:CallbackExecutor。
注意:这里只是设置了默认值,但未真正配置到具体的 Retrofit 类的成员变量当中。
public final class Retrofit { public static final class Builder { ...... private @Nullable HttpUrl baseUrl; ...... // 配置 Retrofit 类的网络请求基地址 baseUrl public 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 参数转化为适合 OkHttp 的 HttpUrl 类型,然后调用 baseUrl() 方法传入刚转化的 HttpUrl,并通过检测最后一个 Segment 来检查传入的参数是不是以 “/” 结尾,如果是则赋值保存传入的 HttpUrl,不是则抛出异常。
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.Factory public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; } } }
Retrofit.Builder.client() 方法为创建网络请求 Call 指定一个自定义调用工厂,这里注意:OkHttpClient 是 Call.Factory 接口的实现类。
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() 方法来创建实例对象。
public final class GsonConverterFactory extends Converter.Factory { // 使用默认的 Gson 实例创建一个 GsonConverterFactory 实例用于数据转换 // 编码到 JSON 并从 JSON 解码(当头部没有指定字符集时)将使用UTF-8 public 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 实例对象的 GsonConverterFactory return new GsonConverterFactory(gson); } private final Gson gson; private GsonConverterFactory(Gson gson) { this.gson = gson; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter); } @Override public 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 集合中。
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() 方法来创建实例对象。
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory { public static RxJava2CallAdapterFactory create() { // 继续调用 RxJava2CallAdapterFactory 有参构造方法,只是 Scheduler 传入为 null return new RxJava2CallAdapterFactory(null); } private final Scheduler scheduler; private RxJava2CallAdapterFactory(Scheduler scheduler) { this.scheduler = scheduler; } @Override public 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 为 false boolean isSingle = rawType == Single.class; // isSingle 为 false boolean isMaybe = rawType == Maybe.class; // isMaybe 为 false if (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) { // 如果是 Response if (!(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 { // 如果都不符合,则默认情况下返回值类型为 observableType responseType = observableType; isBody = true; // isBody 置为 true } // 根据上面的值,实例化 RxJava2CallAdapter 对象 return new RxJava2CallAdapter(responseType, scheduler, isResult, isBody, isFlowable, isSingle, isMaybe, false); } }
RxJava2CallAdapterFactory.creat() 方法中创建 RxJava2CallAdapterFactory 实例对象, 并返回给 Builder.addCallAdapterFactory() 方法作为方法的入参将其放入到 callAdapterFactories 集合中。
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,则创建并配置默认的网络请求执行器 OkHttpClient callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { // 如果没有指定 callbackExecutor,则使用 platform 默认的回调执行器 // Android 平台默认是 MainThreadExecutor callbackExecutor = 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() 再加 1 List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); // 首先添加内置的转换器工厂,其次是 GsonConverterFactory(添加到集合的第二位),最后是platform默认的 defaultConverterFactories converterFactories.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 源码的创建过程。
这里以最简单的获取用户信息为例,没有结合 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);
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() 方法进行处理。
public final class Retrofit { private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); ServiceMethod<?> loadServiceMethod(Method method) { // 首先从 serviceMethodCache 缓存中获取方法对应的 ServiceMethod ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; // 如果不为null,则直接返回该 ServiceMethod synchronized (serviceMethodCache) { // Map 集合中不存在,加锁进行处理,保证方法的唯一性 result = serviceMethodCache.get(method); // 再一次进行获取 if (result == null) { // 当前方法依旧不存在 // 如果 serviceMethodCache 集合中没有找到对应的 ServiceMethod // 通过 ServiceMethod.parseAnnotations() 方法解析注解获取 ServiceMethod result = ServiceMethod.parseAnnotations(this, method); // 将解析获取到的 ServiceMethod,以键值对<Method, ServiceMethod>存入 serviceMethodCache 集合中 serviceMethodCache.put(method, result); } } return result; } }
Retrofit.loadServiceMethod() 方法的主要作用是对接口中的指定方法的注解进行解析得到一个 ServiceMethod 对象,其内部通过 ServiceMethod.parseAnnotations() 方法来完成对指定的 Method 方法的注解进行解析,最后将解析获取到的 ServiceMethod,以键值对<Method, ServiceMethod>存入 serviceMethodCache 缓存集合中。
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 实例和 Retrofit、Method 实例一起转交给 HttpServiceMethod.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; // 请求方式,如:get relativeUrl = builder.relativeUrl; // 请求相对路径 url headers = 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:@POST final 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.List this.parameterTypes = method.getGenericParameterTypes(); // 获取当前网络请求方法传入参数的注解集合 eg (@Query("name") String name) this.parameterAnnotationsArray = method.getParameterAnnotations(); } RequestFactory build() { for (Annotation annotation : methodAnnotations) { // 遍历网络请求方法上面的注解集合 parseMethodAnnotation(annotation); // 解析注解 } if (httpMethod == null) { // 请求方式注解是否为null throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.)."); } if (!hasBody) { // 是否有请求体,parseMethodAnnotation 由这个方法体现:DELETE、GET、OPTIONS、HEAD为 false if (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 实例对象,通过对当前网络请求方法的所有信息进行解析:方法上的注解、方法参数注解、方法参数值等一系列的解析后保存起来。
/** 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?"); } // 请求方法是请求头 并且方法返回不为 Void if (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 就是开始初始化的 OkHttpClient okhttp3.Call.Factory callFactory = retrofit.callFactory; // 使用入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象 return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter); } }
HttpServiceMethod.parseAnnotations() 方法,首先通过 createCallAdapter() 方法创建 CallAdapter 实例对象,然后通过 createResponseConverter() 方法创建 Converter 实例对象用于解析服务端返回的数据,最后使用入参以及上面获取的几个实例对象,新建 HttpServiceMethod 实例对象。
/** 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(); // 获取网络请求接口里的注解,示例代码中是 @GET try { // 根据获取的 returnType 和 annotations,通过 retrofit.callAdapter() 方法获取 CallAdapter return (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() 方法的主要作用是,根据获取的网络请求接口方法的返回值类型 returnType 和 annotations 注解,通过 Retrofit.callAdapter() 方法从 Retrofit 对象中获取对应的网络请求适配器 CallAdapter 实例对象。
public final class Retrofit { final List<CallAdapter.Factory> callAdapterFactories; // 从可用的 callAdapterFactories 工厂集合中返回指定 returnType 的 CallAdapter 实例对象 // 构造 Retrofit 实例对象时进行添加的 CallAdapter.Factory public 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() 方法将获取指定 returnType 和 annotations 注解的 CallAdapter 实例对象的任务转交给 Retrofit.nextCallAdapter() 方法进行查找,找到符合条件的 CallAdapter 实例对象则直接返回,否者抛出报错信息。
/** 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() 方法获取 Converter
return 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 实例对象。
public final class Retrofit { final List<Converter.Factory> converterFactories; // 从可用的 converterFactories 工厂集合中为 ResponseBody 找到指定 type 的 Converter 实例对象 // 构造 Retrofit 实例对象时进行添加的 Converter.Factory public <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 unchecked return (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 获取指定 type 的 Converter 实例对象的任务转交给 Retrofit.nextResponseBodyConverter() 方法进行查找,找到符合条件的 Converter 实例对象则直接返回,否者抛出报错信息。
public final class GsonConverterFactory extends Converter.Factory {
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
// 根据目标类型,利用 Gson.getAdapter() 方法获取相应的 adapter
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
// 使用创建 GsonConverterFactory 时保存的 gson 实例和 adapter 新建 GsonResponseBodyConverter 实例对象
return new GsonResponseBodyConverter<>(gson, adapter);
}
}
GsonConverterFactory.responseBodyConverter() 方法中根据目标类型,利用 Gson.getAdapter() 方法获取相应的 adapter,随后使用创建 GsonConverterFactory 时保存的 gson 实例和 adapter 新建 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() 方法。
/** 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 的具体实现,用来存储一次网络请求的基本信息,比如:Host、URL、请求方法等,还会存储用来适配 OkHttpCall 对象的 CallAdapter、用来创建网络请求 Call 的 Call.Factory、用来进行数据解析的数据转换器 Converter 以及用来构建网络请求 Request 的 RequestFactory 等实例对象。
构建完 HttpServiceMethod 实例对象后,调用其 invoke() 方法并传入网络请求接口的参数,在其 invoke() 方法中首先将前面配置好的 RequestFactory、Call.Factory、Converter 以及输入的网络请求接口的参数构建 OkHttpCall 实例对象,然后将构建的 OkHttpCall 实例对象作为入参传给 RxJava2CallAdapter.adapt() 方法进行下一步的处理。
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; // 数据转换器
}
}
OkHttpCall 是 Retrofit 库中接口 Call 的一个实现类,其入参就是前面配置好的网络请求会用到的一些资源,实现了接口 Call 的几个重要方法:
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 实例对象,后续根据不同的条件新建或转换为符合要求的 Observable Observable<Response<R>> responseObservable = new CallObservable<>(call); Observable<?> observable; if (isResult) { observable = new ResultObservable<>(responseObservable); } else if (isBody) { // 参考 2.6.1 RxJava2CallAdapterFactory.create()的分析,isBody 为 true observable = new BodyObservable<>(responseObservable); } else { observable = responseObservable; } if (scheduler != null) { // 如果设置了 scheduler 则需建立订阅关系 observable = observable.subscribeOn(scheduler); } // Flowable 能够发射0或n个数据,并以成功或者错误事件终止。支持背压,可以控制数据源发射的速度 if (isFlowable) { // 如果是 Flowable,则将 Observable 转换为 Flowable return observable.toFlowable(BackpressureStrategy.LATEST); } if (isSingle) { // 如果是 Single,则将 Observable 转换为 Single,Single 只发射单个数据或者错误事件 return observable.singleOrError(); } // Maybe 能够发射0或者1个数据,要么成功,要么失败。有点类似于 Optional if (isMaybe) { // 如果是 Maybe,则将 Observable 转换为 Maybe return observable.singleElement(); } // Completable 从来不发射数据,只处理onComplete和onError事件。可以看成 Rx 的 Runnable if (isCompletable) { // 如果是 Completable,则将 Observable 转换为 Completable return observable.ignoreElements(); } return observable; } }
RxJava2CallAdapter.adapt() 方法经过判断处理得到所需的可以操作的 Observable 网络请求对象,由于这里只是简单的使用,没有特殊要求的情况下返回的是 BodyObservable 对象。
问题:为什么 InvocationHandler.invoke() 方法不可以直接返回 OKHttpCall 对象,而是调用 CallAdapter.adapt(call, args) 方法进行适配器适配?
答:想象一下,如果没有适配器的话,网络请求返回接口只能直接返回 OkHttpCall,且所有的网络请求都是用 OkHttpCall 进行,这样就失去了 Retrofit 封装的意义,也不够灵活,如:RxJava 的 Observable 就无法支持。而采用适配器模式,将网络请求的核心类 OkHttpCall 进行适配,可根据实际需要通过适配器的适配返回适配后的对象,使得用户在使用 Retrofit 的时候可以自定义想要的返回类型。
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 开始向观察者发送数据 @Override public void onSubscribe(Disposable d) { // 订阅时的操作 } @Override public void onNext(UserInfoBean userInfo) { // UI界面展示获取到的用户信息 } @Override public void onError(Throwable e) { // 出错时的操作 } @Override public void onComplete() { // 完成时的操作 } });
被观察者 Observable 和观察者 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
public abstract class Observable<T> implements ObservableSource<T> { @SchedulerSupport(SchedulerSupport.NONE) @Override public 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) { // NOPMD throw 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 already RxJavaPlugins.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 并实现了该方法。
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() 方法。
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() 方法的执行流程如下:
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) { // 第一次执行时为null try { 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 初始化时添加的 OkHttpClient okhttp3.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() 方法解析网络请求响应。
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 实例对象。
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 实例对象并返回。
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; } }
RealCall 是 OkHttp 库中 Call 的实现类,实现了 Call 接口内部定义的同步与异步请求、取消请求等方法。在 RealCall.newRealCall() 方法中,首先根据入参创建 RealCall 实例对象,然后使用新建的 RealCall 和 OkHttpClient 自身来新建 Transmitter 实例对象并赋值给 RealCall.transmitter 成员变量,最后返回刚创建的 RealCall 实例对象。
OkHttp 后面的代码本文不再深入,后续写文章深入剖析,现在已经获取到 RealCall 实例对象,并调用 RealCall.execute() 方法,后续会通过 RealCall 的拦截器链层层调用后,再一步步返回请求响应 Response,也就是说现在已经获取到网络请求返回的 Response,接下来分析 Retrofit 是如何解析请求响应的。
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) { // 请求成功情况,只是返回数据为null rawBody.close(); return Response.success(null, rawResponse); } ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { // 转换器 Converter 转换 Response 的 ResponseBody T 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() 方法首先获取 Response 的 ResponseBody 响应体,调用 responseConverter.convert() 方法对 ResponseBody 响应体进行数据转换,最后调用 Response.success() 方法构建一个新的 Response 并返回。
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()方法实现的。
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<?>>(); // 实例化一个 HashMap calls.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> 中遍历查找对应的 TypeAdapter for (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() 方法。
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 true String 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 并返回。
public final class Response<T> {
// 由 rawResponse 和 body 创建一个成功的 Response 作为反序列化的 body
public 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() 方法中,由 rawResponse 和 body 创建一个成功的 Response 响应作为反序列化的 body 并返回。
此时,回到 4.3 CallObservable.subscribeActual() 方法,如果请求未取消,且成功拿到数据之后,执行 Observer.onNext() 方法向观察者发送数据,即 UI 界面获取到数据并展示获取到的信息。流程至此,Retrofit 的请求及解析过程也剖析完毕,当然里面还有很多细节,在一篇文章中是很难剖析完全的,感兴趣的可以再深入跟一下,后续有时间,笔者也会继续剖析。
Retrofit 结合 RxJava 来实现网络请求是目前比较常见的异步编程模式,可以提高网络请求的效率和响应速度。
Retrofit 本质上是一个 RESTful 的 Http 网络请求框架的封装,通过大量的设计模式封装了 OkHttp,使得网络请求更加简洁易用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。