您的位置:首页 > 其它

Retrofit原理浅析

2017-12-22 09:09 357 查看

类库原理解析

注解

Retrofit使用注解+java接口来定义后台服务API接口注解主要分为 方法注解 和 参数注解
注解类型作用
@GET方法注解表明HTTP请求方法为GET,(可选)注解的value属性用来设置相对/绝对url
@POST方法注解表明HTTP请求方法为POST,(可选)注解的value属性用来设置相对/绝对url
@PUT方法注解表明HTTP请求方法为PUT,(可选)注解的value属性用来设置相对/绝对url
@DELETE方法注解表明http请求方法为DELETE,(可选)注解的value属性用来设置相对/绝对url
@PATCH方法注解表明HTTP请求方法为PATCH,(可选)注解的value属性用来设置相对/绝对url
@HEAD方法注解表明HTTP请求方法为HEAD,(可选)注解的value属性用来设置相对/绝对url
@OPTIONS方法注解表明HTTP请求方法为OPTIONS,(可选)注解的value属性用来设置相对/绝对url
@HTTP方法注解通过@HTTP注解指定http协议的请求方法,是否允许body,(可选)注解的value属性用来设置相对/绝对url
@FormUrlEncoded方法注解表明发起HTTP请求的RequestBody是form表单方式
@Multipart方法注解表明发起HTTP请求的RequestBody是Multipar方式
@Headers方法注解使用注解的value值数组作为HTTP请求的头,用于一些固定的Header参数
@Streaming方法注解用于需要直接返回流的函数
@Url参数注解HTTP请求的url路径(相对/绝对),可以包含{path_holder},如:http://xxx.com/{user_holder}/detail
@Path参数注解用于动态替换URL路径中的path_holder
@Body参数注解表明此参数用作HTTP请求的body
@Field参数注解表明此参数用作HTTP请求的form表单参数,key为注解的value值
@FieldMap参数注解以map形式传入的form表单参数
@Header参数注解表明此参数用作HTTP请求的header,key为注解的value值
@HeaderMap参数注解以map形式传入的多个header键值对
@Part参数注解表明参数为Http的multipart参数之一
@PartMap参数注解以map形式传入的multipart参数表
@Query参数注解GET方法的query参数,用于拼接完整请求路径
@QueryMap参数注解以map传入的GET方法的query参数,用于拼接完整请求路径

调用流程

通过上面代码可以看到调用关键的就是三步:1 加载对应method的ServiceMethod实例2 使用ServiceMethod实例和方法调用参数创建OkHttpCall3 调用serviceMethod.callAdapter.adapt(okHttpCall)来产生method所定义的返回(Call<T>或者其他自定义CallAdapter支持的返回)

第一步、加载对应method的ServiceMethod实例

ServiceMethod中有以下四个变量比较重要
final okhttp3.Call.Factory callFactory;
final CallAdapter<?> callAdapter;
private final Converter<ResponseBody, T> responseConverter;
private final ParameterHandler<?>[] parameterHandlers;
callFactory是用来创建真正要执行的okhttp3.Call的工厂类,可以Retrofit.Builder中设置,如果不设置,默认会new一个OkHttpClient作为callFactorycallAdapter是用来最终处理OkHttpCall实例并返回接口Method所定义的返回responseConverter 用来将Http请求的结果转换成接口Method所定义的结果(return或者Callback<T>中的T)parameterHandlers 根据接口Method参数的注解所生成的参数处理Handler数组然后我们来看Retrofit.loadServiceMethod方法
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
可以看到此处先检查serviceMethodCache是否有该method对应的ServiceMethod实例缓存,如果没有,则创建一个该method对应的ServiceMethod实例并保存到缓存中。ServiceMethod的创建使用的是建造者模式。在ServiceMethod.Builder的build方法中,通过解析传入的method的方法定义(参数类型,返回类型,参数注解,方法注解)生成对应的callAdapter,responseConverter,parameterHandlers及其他一些创建请求需要用到的信息。
public ServiceMethod build() {
callAdapter = createCallAdapter();
......检查返回结果类型......
responseConverter = createResponseConverter();
//生成方法注解的处理器
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
.....方法与注解合法性检查.....
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
.....注解合法性检查....
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
......方法与注解合法性检查......
return new ServiceMethod<>(this);
}
此处在ServiceMethod.Builder.build()过程在生成过程中还会对method的定义做合法性检查,如:http方法是get就不允许方法参数中有body类型的参数;方法为post则必须有参数为Body类型。

第二步、使用ServiceMethod实例和方法调用参数创建OkHttpCall

获取到method对应的ServiceMethod实例后,会使用该ServiceMethod实例和方法调用的参数Object... args生成一个OkHttpCall。而OkHttpCall实际上是okhttp3.Call的一个包装类,实际调用OkHttpCall的相关执行方法时最终是调用OkHttpCall内部用ServiceMethod.callFactory创建的okhttp3.Call来执行网络请求。

第三步、调用serviceMethod.callAdapter.adapt(okHttpCall)来产生method所定义的返回

Retrofit2默认支持的返回是返回一个Call<T>,利用此Call<T>实例可执行
Response<T> result = call.execute();//同步执行
//异步执行
call.enqueue(new Callback(){
public void onResponse(Call<T> call, Response<T> response){
//TODO
}
public void onFailure(Call<T> call, Throwable t){
//TODO
}
});
其中在Android平台Retrofit2会自动使用主线程handler构造一个ExecutorCallAdapterFactory,调用enqueue(Callback),callback回调会在主线程中回调另外在Retrofit的扩展Adapter中还提供了RxJavaCallAdapterFactory,Java8CallAdapterFactory,GuavaCallAdapterFactory以RxJavaCallAdapterFactory为例,RxJavaCallAdapterFactory创建的callAdapter在执行adapt时将OkHttpCall包装一个Rx的Observable,在Observable被subscribe时才会真正的执行http请求。
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: