Retrofit
本人第一次撰写博客,希望和大家共同学习,有不足或者错误之处望不吝赐教,多谢各位。
我将从Retrofit 的大体框架出发,进而分析Retrofit 各个阶段所做的工作。最后将总结 Retrofit 值得我们学习的地方。
我们都知道Retrofit 并不负责真正的网络请求,而是对 OkHttp 的二次封装,所以有人就会问:为什么放着好好的 OkHttp 不用,非得用Retrofit 呢。这是因为OkHttp 用着不方便,原因有以下几点:

  1. 请求前网络请求配置繁琐,模板代码多,特别是配置复杂的body、请求头、参数的时候。
  2. 网络返回时,客户端需要手动拿到ResponseBody 进行解析,且无法复用。
  3. 网络返回时无法做到线程切换。

Retrofit 就是为了解决这几个问题:网络配置、数据转换、线程切换

一、大体框架

关键类:Retrofit、ServiceMethod、HttpServiceMethod、CallAdapted、RequestFactory、DefaultCallAdapterFactory、OkHttpCall。

作用
Retrofit 网络请求的门面,build方法配置参数,create 方法运用动态代理,生成代理类,进行统一的操作,形成切面
ServiceMethod Retrofit 动态代理执行的方法所属类,解析方法上的注解
HttpServiceMethod ServiceMethod 的子类,用于组装解析好的注解,和retrofit 实例中的属性callFactory、responseConverter、callAdapter
CallAdapted 请求适配发起的类,将okHttp 的Call 转化需要适配的请求
RequestFactory 解析 Retrofit 注解,并作为类属性存储
DefaultCallAdapterFactory 默认网络适配器
OkHttpCall 执行网络请求的类,接收requestFactory,callFactory,responseConverter
Converter 数据转换器
ExecutorCallbackCall Retrofit 构建默认返回的Call 对象

![RetrofitSequence.png](https://img-blog.csdnimg.cn/img_convert/16dcd5ebd11763f7bb1f42895dfe8b37.png#averageHue=#faf9f9&clientId=uc02fdeaa-7c7f-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u7f860ec6&margin=[object Object]&name=RetrofitSequence.png&originHeight=1059&originWidth=1694&originalType=binary&ratio=1&rotation=0&showTitle=true&size=131101&status=done&style=none&taskId=u21e250ac-5d9c-412b-999e-ae3c00199d7&title=Retrofit 流程图 “Retrofit 流程图”)

1.Retrofit 使用方式

//网络请求的接口类
public interface NetworkService {Call<JsonObject> request(@HeaderMap Map<String, Object> headers, @Body RequestBody requestBody);
}//构建 Retrofit 对象Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL).client(okHttpClient).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build();//获得实现接口的实体类对象
networkService = retrofit.create(NetworkService.class);//调用接口方法,实现网络请求
networkService.request().enqueue(new Callback<JsonObject>() {@Overridepublic void onResponse(Call<JsonObject> call, Response<JsonObject> response) {}@Overridepublic void onFailure(Call<JsonObject> call, Throwable t) {}});

Retrofit 使用起来非常方便,共包含以上四个步骤

  1. 书写网络请求的接口类
  2. 构建 Retrofit 对象
  3. 使用retrofit 对象 获得实现接口的实体类对象
  4. 调用接口方法,实现网络请求

这里,如果是没有阅读过源码的同学可能就会有以下问题:

  1. Retrofit 构建者模式中传递的参数有何用,在哪里用
  2. 发起网络请求的实体类对象 networkService 从何而来。为什么使用retrofit 对象能够获得实现接口的实体类对象

我们带着这两个问题进入源码。

问题一:Retrofit 构建者模式中传递的参数有何用,在哪里用

查看 build() 方法源码,可见只是将一些属性传递给 Retrofit,并且会给一些默认值,如callFactory、callbackExecutor、callAdapterFactories。

public Retrofit build() {//服务器地址if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}//Call Factory 在 Build.client 中赋值,网络请求的 Call 对应clientokhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {callFactory = new OkHttpClient();}//回调方法执行器,默认为安卓的执行器 PlatForm.Android.defaultCallbackExecutor Handler 实现Executor callbackExecutor = this.callbackExecutor;if (callbackExecutor == null) {callbackExecutor = platform.defaultCallbackExecutor();}// 网络请求适配器 List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));// 添加数据转换器List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());// Add the built-in converter factory first. This prevents overriding its behavior but also// ensures correct behavior when using converters that consume all types.converterFactories.add(new BuiltInConverters());converterFactories.addAll(this.converterFactories);converterFactories.addAll(platform.defaultConverterFactories());return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

最后调用 Retrofit 构造方法返回Retrofit 实例

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,@Nullable Executor callbackExecutor, boolean validateEagerly) {this.callFactory = callFactory;this.baseUrl = baseUrl;this.converterFactories = converterFactories; // Copy+unmodifiable at call site.this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.this.callbackExecutor = callbackExecutor;this.validateEagerly = validateEagerly;}

其中赋值了Retrofit 所需的基本参数

参数 功能
callFactory 网络请求器,对应 client
baseUrl 访问服务器域名地址
converterFactories 数据转换器
callAdapterFactories 网络请求适配器
callbackExecutor 回调方法执行器

提前先说明各个参数在何处用,让大家形成一个宏观的结构。

问题二:发起网络请求的实体类对象 networkService 从何而来。为什么使用retrofit 对象能够获得实现接口的实体类对象

create 方法使用动态代理,生成代理类,形成切面,完成统一操作。所有的方法都执行到了loadServiceMethod(method).invoke(args != null ? args : emptyArgs) 这一行代码。所以查看loadServiceMethod 方法和 invoke()方法的源码。看一下返回和执行的到底是一个什么东西。

 public <T> T create(final Class<T> service) {Utils.validateServiceInterface(service);return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },new InvocationHandler() {private final Platform platform = Platform.get();private final Object[] emptyArgs = new Object[0];@Override public @Nullable Object invoke(Object proxy, Method method,@Nullable 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);}//关键代码return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);}});}

loadServiceMethod 方法 method(类方法) -> ServiceMethod,里面还有缓存处理,暂时不必关注这一块

  ServiceMethod<?> loadServiceMethod(Method method) {ServiceMethod<?> result = serviceMethodCache.get(method);if (result != null) return result;synchronized (serviceMethodCache) {result = serviceMethodCache.get(method);if (result == null) {//关键代码,解析注解result = ServiceMethod.parseAnnotations(this, method);serviceMethodCache.put(method, result);}}return result;}

查看 ServiceMethod 类 中的 parseAnonotations 方法,这里解析了方法上的注解,组装网络请求的工厂,并在HttpServiceMethod进行进一步的数据解析。

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {//这里解析注解,组装了网络请求的工场RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);//将解析的注解作为HttpServiceMethod构造器参数return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);}

进而查看HttpServiceMethod (ServiceMethod 的子类)的构造器,这里不深入,只查看方法返回的类型

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);}

这里由传入的retrofit 对象获取callFactory,responseConverter,callAdapter(重点关注这个) 以及解析的注解的requestFactory。
CallAdapted 是 HttpServiceMethod 的子类。

  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {private final CallAdapter<ResponseT, ReturnT> callAdapter;CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,Converter<ResponseBody, ResponseT> responseConverter,CallAdapter<ResponseT, ReturnT> callAdapter) {super(requestFactory, callFactory, responseConverter);this.callAdapter = callAdapter;}@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {return callAdapter.adapt(call);}}

回过头查看动态代理中的invoke方法,发现最后调用的是 HttpServiceMethod 的invoke 方法

  @Override final @Nullable ReturnT invoke(Object[] args) {Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);return adapt(call, args);}

invoke 方法中构造了一个 OkHttpCall 的实例,最后执行 adapt 函数,即执行到了上述子类 CallAdapted 的 adapt 函数。

@Override protected Object adapt(Call<ResponseT> call, Object[] args) {call = callAdapter.adapt(call);}

所以最终我们要查看 callAdapter 究竟是如何构建的。
这就涉及到细节了,这里就放到下一节说明。这里我们知道 callAdapter只是将 OkHttpCall 适配成为 ExecutorCallbackCall,所以最终接口方法执行后返回的就是一个 ExecutorCallbackCall 的实例。

Retrofit 大体框架相关推荐

  1. ~ 如何用C++自制一个日麻游戏 ~(一)大体框架构建 § 2 数据结构

    导入 有了整个游戏的流程构想,就需要把它写进类里,但要清楚类的互相包含关系 正题 以下树状图写出了互相包含的关系: Maj_system 是整的一局游戏,从洗牌发牌,到荣和算点,包含了四家(Oppon ...

  2. Retrofit + Rxjava框架学习使用(举例:酷狗搜索和详情接口)

    在我上一篇博客Retrofit框架简单学习使用基础上修改. 依赖: dependencies {implementation 'com.squareup.retrofit2:retrofit:2.5. ...

  3. HTML(1)大体框架

    (本人也是在一边摸索一边总结,可能有些地方不够全面,还望各位大佬留言补充,谢谢啦) 1.首先新建一个文本文档,双击打开. 2.如图的两行是必要的代码. 3.对于一个网页,自然需要它的名称." ...

  4. Spring源码之Spring的大体框架

    Spring源码(一)----了解Spring的大体框架 Spring的源码数量特别多,在我下载了Spring FrameWork源码后,发现有些无从学起,那么就一步一步来,先不管其他,先了解一下Sp ...

  5. 小白学python(爬虫知识1(大体框架)

    定义框架 主函数: 1.初始网址 2.获取数据 3.保存数据 大体流程 from bs4 import BeautifulSoup # 解析网页 import re # 正则提取 import url ...

  6. OKHTTP和retrofit 网络框架集成的有https验证的APP破解抓包

    由于公司需要,批不得以要从友商的APP上面抓些数据来用,根据一般的经验我直接用Fiddler抓包工具来抓,平时抓些基础数据用这个工具还是很坚挺的,使用也很简单.但是连接上手机后具体操作才发现,返回的连 ...

  7. Android之全面解析Retrofit网络框架封装库

    转载请标明出处:[顾林海的博客] 前言 Retrofit是Square公司推出的一个HTTP的框架,主要用于Android和Java,Retrofit会将每一个HTTP的API请求变成一个Java的接 ...

  8. 开源框架相关面试问题-retrofit网络框架面试问题讲解

    retrofit使用简介: 在retrofit中通过一个接口作为Http请求的api接口. 注意:@GET("url")中的url只是一个路径,不包含主机号的. 创建一个retro ...

  9. Retrofit网络框架的封装使用

    retrofit的使用实例(封装以后比较简单明了) //联网登录请求的使用Map<String, String> map = new HashMap<>();map.put(& ...

最新文章

  1. 中国联通备战5G MWC发布《Edge-Cloud平台架构及产业生态白皮书》
  2. SQL Server 2005/2008 用户数据库文件默认路径和默认备份路径修改方法
  3. 重磅新政!土拍规则大调整!土地市场将迎“大降温”
  4. 大学生计算机实验基础考试,大学生计算机基础考试题库完整(56页)-原创力文档...
  5. boost::function_types::is_member_function_pointer的用法测试程序
  6. 重学算法第三期|数据结构与算法001
  7. Vue2.0 + ElementUI 手写权限管理系统后台模板(三)——页面搭建
  8. python将图片转动漫_python实现了照片转化为动漫模式
  9. Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件(转)
  10. 弱监督学习总结(1)
  11. 【Elasticsearch教程20】Pinyin拼音分词器 以及多音字修改
  12. 企业微信自建内部应用Demo源码,附在线Demo及视频讲解,创建测试公司及测试应用简单配置即可使用
  13. 题解 | Guessing ETT-2019牛客暑期多校训练营第三场C题
  14. python中abs和fabs的区别_abs()与fabs()的速度差异和fabs()的优势
  15. Android GreenDao
  16. saas商城跟源码商城对比优势在哪里
  17. JS编码解码对应C#编码解码
  18. 突破生命法则极限!它会是外星生命的遗传密码?
  19. 2.参考线平滑算法解析及实现
  20. 174.127.195.176/bbs/index.php,[原创]一次逆向fb寻找密码的记录及还原相关算法

热门文章

  1. 微信小游戏从零开始申请软著到上线
  2. win10有信号没有网络连接到服务器,win10系统显示网络连接正常但没有网络,无法上网的办法介绍...
  3. 喹啉羧酸类 DHODH 抑制剂用于治疗急性髓系白血病
  4. 人见人爱A+B(C++)
  5. python rgb转换为gray
  6. 带界面的程序化交易软件-从今天开始
  7. 智能硬件产品盈利模式
  8. Task运行过程分析2
  9. 使用AHK减少鼠标和方向键的使用频率,高效编辑
  10. 激光雷达公司一径科技完成C轮融资,将加快核心芯片自研