Retrofit原理浅析

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并返回结果。

调用流程 
通过上面代码可以看到调用关键的就是三步:

  1. 加载对应method的ServiceMethod实例
  2. 使用ServiceMethod实例和方法调用参数创建OkHttpCall
  3. 调用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定义的转置模式进行转换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值