Retrofit 源码深度解析-(1)序言
1.1 简介
Retrofit
是一个类型安全的Android和Java HTTP客户端,内部基于OkHttp
,以一种优雅的方式(接口的形式)提供给用户以发起HTTP请求。
1.2 使用方式
Retrofit
的使用方式比较简单,定义HTTP
的java接口,构建一个Retrofit
对象,使用Retrofit实例
创建接口实例,进行调用。
@Test
public void test() throws IOException {
// 创建Build
Retrofit.Builder builder = new Retrofit.Builder();
// 添加build信息
builder.client(new OkHttpClient());
builder.baseUrl("https://www.baidu.com/");
// 传入CallAdapterFactory
builder.addCallAdapterFactory(new DefaultCallAdapt.DefaultCallAdaptFactory());
// 传入ConverterFactory
builder.addConverterFactory(new MyConverterFactory());
// 实例化Retrofit对象
Retrofit retrofit = builder.build();
// 构建接口实例并调用
Response stringResponse = retrofit.create(BaiduApi.class).get1("").execute();
// 输出结果
System.out.println(JSON.toJSON(stringResponse));
}
可以看到,Retrofit
的使用方式很优雅,免去了请求参数、响应参数的转化等繁琐操作。
下面就主要几个关键参数先简单说明一下:
- client
该方法的签名信息为
Builder client(okhttp3.OkHttpClient client)
可以看到,需要传入一个OkHttpClient实例,这个方法是用来给使用者进行扩展的,在构建OkHttpClient时,可以自定义自己的插件、连接池等等信息
- baseUrl
顾名思义,定义baseUrl。
所以在定义Service接口时,只需要定义具体的path即可
- CallAdapterFactory
这个工厂是用来构建CallAdapter的,CallAdapter用来干嘛下面会详细讲到
- ConverterFactory
这个工厂是用来构建Converter的,Converter的定义是将返回结果进行转换成业务需要的对象,下面会详细描述。
其中 CallAdapterFactory
和ConverterFactory
的代码如下
public class DefaultCallAdapt<R> implements CallAdapter<R, Call<R>> {
Type returnType;
public DefaultCallAdapt(Type returnType) {
this.returnType = returnType;
}
@Override
public Type responseType() {
return returnType;
}
@Override
public Call<R> adapt(Call<R> call) {
// 这个适配器不做啥操作,直接返回
return call;
}
public static class DefaultCallAdaptFactory extends Factory {
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 获取第0个定义的参数类型
final Type responseType =getParameterUpperBound(0, (ParameterizedType) returnType);
return new DefaultCallAdapt(responseType);
}
public static Type getParameterUpperBound(int index, ParameterizedType type) {
Type[] types = type.getActualTypeArguments();
if (index < 0 || index >= types.length) {
throw new IllegalArgumentException(
"Index " + index + " not in range [0," + types.length + ") for " + type);
}
Type paramType = types[index];
if (paramType instanceof WildcardType) {
return ((WildcardType) paramType).getUpperBounds()[0];
}
return paramType;
}
public static Class<?> getRawType(Type type) {
return Factory.getRawType(type);
}
}
}
static class MyConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return new ToStringConverterFactory().responseBodyConverter(type, annotations, retrofit);
}
}
static class ToStringConverterFactory extends Converter.Factory {
static final MediaType MEDIA_TYPE = MediaType.get("text/plain");
@Override
public Converter<ResponseBody, String> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (String.class.equals(type)) {
// 简单的返回string
return ResponseBody::string;
}
return null;
}
@Override
public Converter<String, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
if (String.class.equals(type)) {
return value -> RequestBody.create(MEDIA_TYPE, value);
}
return null;
}
}
public interface BaiduApi {
@GET("/")
Call<String> get1(@Query("aaa") String args);
@GET("/")
Response<String> get2(@Query("aaa") String args);
}
由上面的例子看到,使用Retrofit
的典型步骤分为三步:
- 使用配置信息构建Retrofit实例
- 使用Retrofit实例,构建Service实例
- 调用Service实例方法,发起请求
接下来,根据这三个步骤,深入剖析Retrofit
的源码以及其精髓所在。