本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众号,谢谢!
在上章节《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<T>转换成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方法就介绍完毕。
838794-506ddad529df4cd4.webp.jpg
搜索微信“顾林海”公众号,定期推送优质文章。
网友评论