在网络请求中由于各种业务需要,定义的接口入参、出参类型各不相同
以往做法都是在请求成功的回调方法中自行解析response的内容,写法不一又显得重复累赘。
而retrofit采用了2个接口来解决该问题。
retrofit中的2个类型转换接口
1、CallAdapter接口
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory {
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
}
}
responseType方法:
你需要的返回类型
adapt方法:
将请求Call对象转换为Java的T泛型对象
Factory工厂负责创建CallAdapter的适配器,新创建的适配器实体类就得实现以上2个接口方法
2、Converter接口
public interface Converter<F, T> {
@Nullable T convert(F value) throws IOException;
abstract class Factory {
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit);
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit);
}
}
convert方法:
将类型F转换为T,实现数据类型转换
Factory工厂中的方法分别负责创建请求和响应的转换器
使用:
1、保存(set)
提供addCallAdapterFactory方法把适配器创建者(工厂)存在callAdapterFactories变量中,这里将存放用户自己实现的工厂类及工厂所负责创建的适配器
提供addConverterFactory方法把类型转换器创建者(工厂)存在converterFactories变量中,这里也存放着用户的相关实现类
2、获取(get)
提供nextCallAdapter方法获取CallAdapter接口对象,这里就是获取了第1步变量中的值
提供nextRequestBodyConverter方法获取Converter接口对象,这里也是获取了第1步变量中的值
3、ServiceMethod类负责解析注册进来的注解
提供createCallAdapter方法获取CallAdapter,这里就是通过第2步的方法获取
提供createResponseConverter方法创建Converter,这里也是通过第2步的方法获取
在parseAnnotations方法中,获取callAdapter的responseType类型,并传给Converter的工厂的方法,方便用户创建转换器
如Gson的转换器便是这样创建的:
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
4、在Call的实现类OkHttpCall中通过代码
T body = responseConverter.convert(catchingBody);将最初始的response转换成T(这样就得到了用户需要的数据类型)
5、调用入口流程
用户通过create方法创建完请求之后(这里通注解方式把请求和响应的数据类型都注册给retrofit了),
create的回调方法invoke就被调用了。(关于回调可参考[https://blog.csdn.net/u010082177/article/details/99311585](https://blog.csdn.net/u010082177/article/details/99311585))
在invoke回调方法中:
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
调用loadServiceMethod方法完成对方法的注解解析
调用invoke方法其实时调用了ServiceMethod的实现类HttpServiceMethod的invoke方法
return callAdapter.adapt(new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
调用adapter方法才真正调用了CallAdapter的实现类的方法,该方法的返回类型就是用户想要的类型
参数new OkHttpCall把获取的convert适配器对象都传给了OkHttpCall,然后就获取到了第4步中的类型。
总结:
在碰到需要处理不同的数据类型转换时,可参考以上2个接口的设计
接口定义了一种能力,该能力在具体的实现类得以体现,而接口中的工厂只是按需来创建不同的实现类。