Retrofit是基于OKhttp实现的网络请求框架,是对OKhttp的优秀封装,使用起来更加方便、简洁,特别还提供了RxJava的支持。Retrofit框架中采用了大量的设计模式来实现超级解耦,所以本文的初衷希望通过Retrofit源码的解读,来学习一下作者优秀的设计思想
一个Retrofit网络请求,一般会经历如下步骤:
1.创建Retrofit实例对象,配置请求相关参数,比如URL、请求适配器、数据转换器等,使用的设计模式有建造者模式、工厂模式、适配器模式
2.通过动态代理模式创建接口的代理对象
3.调用接口代理对象的对应方法获得一个请求对象,通过请求对象的enqueue方法进行异步请求,或execute方法进行同步请求
下面来看一个Retrofit网络请求的示例代码
// 一:创建retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://xxx.com/") // 设置Url
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析
.build();
// 二:创建网络请求接口实例
ApiServer service= retrofit.create(ApiServer.class);
//调用api接口,获取一个请求对象Call
Call<ResponseBean> call = service.post("args");
// 三:异步请求
call.enqueue(new Callback<Translation1>() {
//请求成功回调
@Override
public void onResponse(Call<ResponseBean> call, Response<ResponseBean> response) {
// 请求处理,输出结果
System.out.println(ResponseBean.toString);
}
//请求失败回调
@Override
public void onFailure(Call<ResponseBean> call, Throwable throwable) {
System.out.println("请求失败");
System.out.println(throwable.getMessage());
}
});
接下来就基于上面这个示例来分析一下Retrofit的源码
一:构建Retrofit实例
1.Retrofit构建器
Retrofit实例是通过构造者模式的Builder类进行创建的
public static final class Builder {
//请求支持的平台,这里是android平台
private Platform platform;
//OKhttp请求对象Call的生产工厂
private okhttp3.Call.Factory callFactory;
//url配置
private HttpUrl baseUrl;
//数据转换器工厂集合
private List<Converter.Factory> converterFactories = new ArrayList<>();
//请求适配器工厂集合
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
//回调方法执行器
private Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
// 默认添加数据转换器
converterFactories.add(new BuiltInConverters());
}
public Builder() {
this(Platform.get());
}
...
}
可以看到构建一个Retrofit实例的相关配置参数,比较常见的有baseUrl的配置、数据转换器工厂和请求适配器工厂的配置,先来看看url的配置
2.baseUrl的配置
public Builder baseUrl(String baseUrl) {
//不能是null
checkNotNull(baseUrl, "baseUrl == null");
//解析成HttpUrl
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
//baseUrl必须以/结尾
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
主要是检查baseUrl的合法性,不能为null而且要以 /结尾,然后赋值给Builder的baseUrl
3.数据转换器工厂
数据转换器的作用当然就是用来转换数据格式的,比如发送或接收数据的时候,用Gson可以将Json格式的字符串转换为Java对象或将Java对象转换为Json格式的字符串
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
Retrofit默认实现了Gson的数据转换工厂, 使用的话要导入对应的包com.squareup.retrofit2:converter-gson:2.0.2,当然数据转换器也可以自定义,一般就使用Gson就可以了
实现数据转换器工厂需要继承Converter接口的Factory类,这个工厂类可以生产多个产品角色,所以属于抽象工厂模式,convert是数据转换器需要实现的方法,如下
public interface Converter<F, T> {
//数据转换器的实现方法
T convert(F value) throws IOException;
//数据转换器工厂的抽象类,抽象工厂模式
abstract class Factory {
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
}
}
抽象类Factory是所有数据转换工厂的父类,子类需要实现responseBodyConverter和requestBodyConverter两个主要方法,分别用来获取响应体和请求体的数据转换器,有了数据转换器&#x