Retrofit2源码分析

Retrofit简述

Retrofit是对OkHttp网络请求的封装,利用注解使其转变为面向接口编程,利用动态代理将接口转变成具体实例,再利用反射和注解遍历接口方法的各种网络请求参数,并对其封装和缓存,利用策略模式适配不同的请求平台,例如,android、rx-java等。使用工厂模式返回不同的网络请求call和数据转换器,在用回调执行器切换线程,使其在主线程中返回数据。

几个概念

这里写图片描述

要搞清楚retrofit的源码需要先知道上述概念。图片解释的很清楚,这里不再赘述。

源码分析

Retrofit初始化

 Retrofit retrofit = new Retrofit.Builder()
                                 .baseUrl("http://fanyi.youdao.com/")
                                 .addConverterFactory(GsonConverterFactory.create())
                                 .build();

上面这段代码我们再熟悉不过了,主要是Retrofit的示例构造过程。利用了builder模式,使使用者可以不关心构造的过程。

这一步主要是初始化一些数据:
serviceMethod:包含所有网络请求信息的对象
baseUrl:网络请求的url地址
callFactory:网络请求工厂
adapterFactories:网络请求适配器工厂的集合
converterFactories:数据转换器工厂的集合
callbackExecutor:回调方法执行器

大家都知道builder创建对象的好处是大量的参数是有默认值的再用户不设置的时候就会采用默认的参数。这样既灵活,兼容性又好。
网络请求适配器工厂和数据转换器工厂都用自己的默认值,而且用户设置的值和默认值都会存到一个集合中,在网络请求的时候会根据接口设置的参数和平台信息封装serviceMethod,在serviceMethod中网络请求适配器工厂和数据转换器工厂只有一个值,不是集合,而这个值就是上面工厂集合里选出来的。
之所以要设置网络请求适配器,是为了支持不同的返回值,例如如果是rx-java,返回值必须是Observable,需要对原始的call进行再次封装。

请求接口创建

大家都知道利用Retrofit网络请求只需创建一个java接口在其方法上利用注解配置请求参数和请求方法等信息。代码如下:

<-- 步骤1:定义接收网络数据的类 -->
<-- JavaBean.java -->
public class JavaBean {
  .. // 这里就不介绍了
  }

<-- 步骤2:定义网络请求的接口类 -->
<-- AccessApi.java -->
public interface AccessApi {
    // 注解GET:采用Get方法发送网络请求
    // Retrofit把网络请求的URL分成了2部分:1部分baseurl放在创建Retrofit对象时设置;另一部分在网络请求接口设置(即这里)
    // 如果接口里的URL是一个完整的网址,那么放在创建Retrofit对象时设置的部分可以不设置
    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")

    // 接受网络请求数据的方法
    Call<JavaBean> getCall();
    // 返回类型为Call<*>,*是解析得到的数据类型,即JavaBean
}

<-- 步骤3:在MainActivity创建接口类实例  -->
AccessApi NetService = retrofit.create(AccessApi.class);

<-- 步骤4:对发送请求的url进行封装,即生成最终的网络请求对象  --> 
        Call<JavaBean> call = NetService.getCall();

这里主要是利用了动态代码的模式和外环设计模式。
利用动态代理获取示例后,在用户调用其中的方法的时候,会执行invoke方法,在这个方法中判断是执行了那个方法,在在集合中获取相应的ServiceMethod,利用serviceMethod,创建OkHttpCall(这个不是Okhhtp的类只是一个代理类)。再返回serviceMethod,出发网络请求。

// 下面会详细介绍 invoke()的实现
            // 即下面三行代码
            ServiceMethod serviceMethod = loadServiceMethod(method);     
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);

serviceMethod中包含此接口所需要网络请求的所有的数据,一部分来自retrofit示例,一部分来自接口的参数。
return serviceMethod.callAdapter.adapt(okHttpCall);
这里采用了装饰模式:ExecutorCallbackCall = 装饰者,而里面真正去执行网络请求的还是OkHttpCall
使用装饰模式的原因:希望在OkHttpCall发送请求时做一些额外操作。这里的额外操作是线程转换,即将子线程切换到主线程

网络请求

Retrofit默认使用OkHttp,即OkHttpCall类(实现了 retrofit2.Call接口)
但可以自定义选择自己需要的Call类
OkHttpCall提供了两种网络请求方式:
同步请求:OkHttpCall.execute()
异步请求:OkHttpCall.enqueue()

这里不在阐述,主要是对返回状态的判断和返回数据的处理,以及是否需要线程切换,以及是否对数据进行二次封装。
盗个图总结一下:

这里写图片描述

本文大量参考了下文
https://blog.csdn.net/carson_ho/article/details/73732115#commentsedit

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值