在上章节《Android 小知识 - 剖析 Retrofit 中的网络请求流程以及相关参数》中介绍了 Retrofit 的成员变量, 以及静态内部类 Builder 中的成员变量, 本节继续讲解 Builder 类中的相关方法.
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("http://icould.glh/")
- .addConverterFactory(GsonConverterFactory.create())
- .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
- .build();
通过 Builder 的 baseUrl 方法来设置 http 的基地址, 先进入 baseUrl 方法.
- public Builder baseUrl(String baseUrl) {
- checkNotNull(baseUrl, "baseUrl == null");
- HttpUrl httpUrl = HttpUrl.parse(baseUrl);
- if (httpUrl == null) {
- throw new IllegalArgumentException("Illegal URL:" + baseUrl);
- }
- return baseUrl(httpUrl);
- }
在 baseUrl 方法中, 将传入的 String 类型的 baseUrl 通过 HttpUrl 的 parse 方法转换成 HttpUrl 对象, 将转换后的 httpUrl 实例传入 baseUrl 方法, 注意这里传入 baseUrl 方法的是 HttpUrl 对象, 我们继续看 baseUrl(HttpUrl) 方法.
- public Builder baseUrl(HttpUrl baseUrl) {
- checkNotNull(baseUrl, "baseUrl == null");
- List<String> pathSegments = baseUrl.pathSegments();
- if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
- throw new IllegalArgumentException("baseUrl must end in /:" + baseUrl);
- }
- this.baseUrl = baseUrl;
- return this;
- }
通过 checkNotNull 方法判断 HttpUrl 对象是否为空, 接着通过 HttpUrl 的 pathSegments() 方法将 url 拆分成多个独立的碎片, 为了方便比较, 将创建 Retrofit 实例贴出来:
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("http://icould.glh/")
通过 baseUrl 方法设置 http 的 url 时, 在最后是以'/'反斜杠结尾的, 下面的 if 语句中判断拆分后的最后字符串是否为空, 拆分后的数组最后一个为空, 说明 http 的 url 是以'/'结尾, 反之 http 的 url 不是以'/'结尾, 就会抛出异常, 最后将 baseUrl 赋值给 Builder 的成员变量 baseUrl.
介绍完 baseUrl 方法, 继续看下一个方法 addConverterFactory 方法:
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("http://icould.glh/")
- .addConverterFactory(GsonConverterFactory.create())
- .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
- .build();
addConverterFactory 方法是用于设置数据解析器, 进入 addConverterFactory 方法看看到底做了哪些操作.
- public Builder addConverterFactory(Converter.Factory factory) {
- converterFactories.add(checkNotNull(factory, "factory == null"));
- return this;
- }
addConverterFactory 方法所做的工作很简单, 就是将 factory 添加到数据解析器工厂的集合中. 回到前面 addConverterFactory 方法, 看到传入的是 GsonConverterFactory 对象, 而 GsonConverterFactory 对象是通过 GsonConverterFactory 的 get() 方法创建的, 点进去看下.
- public static GsonConverterFactory create() {
- return create(new Gson());
- }
create 方法内部先是创建了 Gson 对象, 这个 Gson 就是 goole 提供的 Gson, 用于解析 JSON 数据用的, 创建完 Gson 对象后调用 create 方法并传入刚创建后的 Gson 对象.
- public static GsonConverterFactory create(Gson gson) {
- if (gson == null) throw new NullPointerException("gson == null");
- return new GsonConverterFactory(gson);
- }
方法很简单, 创建一个 GsonConverterFactory 对象并返回, 我们进入 GsonConverterFactory 的构造函数中.
- private final Gson gson;
- private GsonConverterFactory(Gson gson) {
- this.gson = gson;
- }
GsonConverterFactory 的构造函数只做了赋值操作, 将创建好的 Gson 对象赋值给 GsonConverterFactory 的成员变量 gson.
介绍完 addConverterFactory 方法后, 接着看 addCallAdapterFactory 方法:
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("http://icould.glh/")
- .addConverterFactory(GsonConverterFactory.create())
- .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
- .build();
addCallAdapterFactory 方法用于设置适配的平台, 这里使用的是 RxJava 平台, 我们看下 addCallAdapterFactory 的具体操作.
- public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
- callAdapterFactories.add(checkNotNull(factory, "factory == null"));
- return this;
- }
代码还是很简单, 就是将 factory 添加到适配器工厂的集合中去. 回到前面, 看看 addCallAdapterFactory 方法传入的这个 Factory, 是通过 RxJavaCallAdapterFactory 工厂类的 create() 方法来创建的.
- public static RxJavaCallAdapterFactory create() {
- return new RxJavaCallAdapterFactory(null, false);
- }
create 方法内部直接通过 new 关键字创建了 RxJavaCallAdapterFactory 对象.
- public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
- ...
- }
RxJavaCallAdapterFactory 继承了 CallAdapter 的内部类 Factory.
先看 CallAdapter 的作用, CallAdapter 作用就是通过 Retrofit 中 Call 转换成 Java 对象, Retrofit 中的 Call 对象和 OkHttp 中的 Call 对象是不一样的, Retrofit 中的 Call 是对 OkHttp 中的 Call 进行了封装, 也就是说通过 Retrofit 来进行网络请求, 最终都是通过 OkHttp 来进行请求的. 在转换 Java 对象前, 需要先创建 Retrofit 中的 Call 对象, 然后通过 Call 对象发送 http 请求, 服务器会返回响应的数据, 这个时候通过 converter 数据转换器, 将服务器返回的 Response 转换成我们需要的 Java 对象.
- public interface CallAdapter<R, T> {
- Type responseType();
- T adapt(Call<R> call);
- }
在 CallAdapter 接口中定义了一个 responseType() 方法并返回 Type 类型, 这个方法的作用就是返回解析后的类型. 看下面网络请求接口:
- public interface NetworkInterface {
- @GET("news/newsDetail")
- Call<MyResponse> getNewsDetails(@QueryMap Map<String,String> map);
- }
CallAdapter 接口中的 responseType 方法返回的就是 MyResponse 这个类型的对象.
- public interface CallAdapter<R, T> {
- Type responseType();
- T adapt(Call<R> call);
- }
继续看第二个方法 adapt, 这里的泛型 T 是指需要转换接口的返回类型, adapt 方法传入一个 Call 对象, 这个 Call 对象就是 OkHttp 的 Call 对象, 如果对应的是 RxJava 的话, 这里的 T 对应的就是 RxJava 当中的类型.
继续看 CallAdapter 内部类 Factory:
- public interface CallAdapter<R, T> {
- ...
- abstract class Factory {
- public abstract @Nullable retrofit2.CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
- Retrofit retrofit);
- ...
- protected static Class<?> getRawType(Type type) {
- return Utils.getRawType(type);
- }
- }
- }
get 方法的作用是根据接口的返回类型以及注解类型来得到实际需要的 CallAdapter;getRawType 方法返回的是原始的类型.
RxJavaCallAdapterFactory 实现 Factory 抽象类, 用来提供具体的适配逻辑, 回到 RxJavaCallAdapterFactory, 先看 get 方法的实现:
- @Override
- public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
- Class<?> rawType = getRawType(returnType);
- ...
- return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
- false);
- }
在 get 方法中, 先通过 getRawType 拿到原始数据类型, 通过这个原始数据类型进行各种设置, 最后创建 RxJavaCallAdapter 对象并返回. 创建完 RxJavaCallAdapter 对象后, 最终调用 adapt 方法将我们的 Call 请求转换成每一个平台所适用的类型. adapt 方法在接口 CallAdapter 中定义的, 在源码中找到 RxJavaCallAdapter 实现了 CallAdapter 接口, 我们看看 RxJavaCallAdapter 中的 adapt 实现.
- @Override public Object adapt(Call<R> call) {
- Observable.OnSubscribe<Response<R>> callFunc = isAsync
- ? new CallEnqueueOnSubscribe<>(call)
- : new CallExecuteOnSubscribe<>(call);
- Observable.OnSubscribe<?> func;
- if (isResult) {
- func = new ResultOnSubscribe<>(callFunc);
- } else if (isBody) {
- func = new BodyOnSubscribe<>(callFunc);
- } else {
- func = callFunc;
- }
- Observable<?> observable = Observable.create(func);
- if (scheduler != null) {
- observable = observable.subscribeOn(scheduler);
- }
- if (isSingle) {
- return observable.toSingle();
- }
- if (isCompletable) {
- return observable.toCompletable();
- }
- return observable;
- }
使用过 RxJava 的同学应该对上面的代码非常熟悉了, 将我们传入的 OkHttp 的 Call 对象设置给 OnSubscribe 对象, 接着创建 Observable 被观察者的实例, 并将 OnSubscribe 与被观察者绑定, 最后判断 scheduler 调度器是否为空, 如果不为空, 就调用 observable 的 subscribeOn 方法在指定的调度器执行操作. 关于 RxJava 的相关知识后面会另开文章进行讲解, 这里大家先有个印象, 知道整体的流程即可.
到这里 baseUrl,addConverterFactory 以及 addCallAdapterFactory 方法就介绍完毕.
来源: https://juejin.im/post/5bdbbae9f265da396146190a