您的位置:首页 > 其它

Retrofit原理浅析

2017-12-15 10:26 381 查看
Retrofit是Square组织开发维护的一款网络框架。Retrofit非常适合处理RESTful风格的网络接口。Retrofit通过注解和动态代理简化了网络请求的代码工作量,与OKHttp为同一组织开发,能够很好的结合使用。

Retrofit和okhttp配合使用的优点

Retrofit其实是在okhttp的基础之上进行了封装。把网络请求都交给给了Okhttp,我们只需要通过简单的配置就能使用retrofit来进行网络请求了使得使用上更加简洁明了,并且配置灵活,能达到解耦的效果。

Retrofit非常巧妙的用注解来描述一个HTTP请求,将一个HTTP请求抽象成一个Java接口,然后用了Java动态代理的方式,动态的将这个接口的注解“翻译”成一个HTTP请求,最后OkHttp去发送这个HTTP请求。

Retrofit框架存在的优势:

① Retrofit使用注解方式,大大简化了我们的URL拼写形式,而且注解含义一目了然,简单易懂;

② Retrofit使用简单,结构层次分明,每一步都能清晰的表达出之所以要使用的寓意;

④ Retrofit支持同步和异步执行,使得请求变得异常简单,只要调用enqueue/execute即可完成;

④ Retrofit更大自由度的支持我们自定义的业务逻辑,如自定义Converters。

1. Retrofit介绍

一个用于android和Java平台的类型安全的网络框架。 

Retrofit 是一个Square开发的类型安全的REST安卓客户端请求库。这个库为网络认证、API请求以及用OkHttp发送网络请求提供了强大的框架 。 

Retrofit 把REST API返回的数据转化为Java对象,就像ORM框架那样,把数据库内的存储的数据转化为相应的Java bean对象。

那么我们知道Retrofit是一个类型安全的网络框架,而且它是使用REST API的,接下来我们看看什么是REST吧。

2. REST 介绍:资源表现层状态转化

Resources Representational State Transfer 

资源表现层状态转化
1.每一个URI代表一种资源
2.客户端和服务器之间,传递这种资源的某种 表现层(“资源”具体呈现出来的形式,比如.txt,.png,.jpg)
3.客户端通过四个HTTP动词(GET用来获取资源,POST用来新建或更新资源,PUT用来更新资源,DELETE  用来删除资源)对服务器端资源进行操作,实现”表现层状态转化”
1
2
3
4

类库原理解析

注解

Retrofit使用注解+java接口来定义后台服务API接口

注解主要分为 方法注解 和 参数注解


 


 



生成动态代理实例

Retrofit使用的关键一步就是Retrofit.create函数创建接口动态代理的示例,代码如下
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();

@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

可以看到是为接口的每个method创建了一个对应的ServiceMethod,并使用这个ServiceMethod对象创建OkHttpCall,并使用ServiceMethod实例的callAdapter来调用okhttpCall并返回结果。

调用流程 

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

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

ServiceMethod中有以下四个变量比较重要
final okhttp3.Call.Factory callFactory;
final CallAdapter<?> callAdapter;
private final Converter<ResponseBody, T> responseConverter;
private final ParameterHandler<?>[] parameterHandlers;
1
2
3
4
callFactory是用来创建真正要执行的okhttp3.Call的工厂类,可以Retrofit.Builder中设置,如果不设置,默认会new一个OkHttpClient作为callFactory
callAdapter是用来最终处理OkHttpCall实例并返回接口Method所定义的返回
responseConverter 用来将Http请求的结果转换成接口Method所定义的结果(return或者Callback中的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;
}
1
2
3
4
5
6
7
8
9
10
11

可以看到此处先检查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);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

此处在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,利用此Call实例可执行
Response<T> result = call.execute();//同步执行
1


//异步执行
call.enqueue(new Callback(){
public void onResponse(Call<T> call, Response<T> response){
//TODO
}
public void onFailure(Call<T> call, Throwable t){
//TODO
}
});
1
2
3
4
5
6
7
8
9

简单总结一下Retrofit的主要内部实现:

1.Retrofit实例的构造,填充一些参数,比如将在后面谈到的callAdapterFactory、convertFactory,以及baseUrl,callFactory(与callAdapterFactory作区分,若不指定,则为一个默认的OkHttpClient,可以根据需要创建一个OkHttpClient,然后对这个OkHttpClient添加对应的属性,以实现不同的网络处理机制)。

2.Retrofit调用create创建一个代理实体,而代理关键部分在于创建一个ServiceMethod,ServiceMethod收集接口方法的参数类型以及对应的注解,组成一个有关网络请求的参数类型集合。

3.ServiceMethod与接口方法传入的参数共同作用传入OkHttpCall,构成一个Call对象,经过CallAdapterFactory的适配,返回。因此接口方法可以理解为最后获得这个Call对象(真实来说应该是OkHttpCall)。

4.Call对象调用enqueue实际使用的是OkHttp的RealCall的enqueue方法,因此Retrofit的Call对象可以看成是OkHttp的Call的一个封装。当然,这不是一个简单的封装,在网络请求获得响应后,OkHttpCall还会对返回的信息进行转置,根据ConvertFactory定义的转置模式进行转换。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: