retrofit原理分析,自学Flutter_m0_65145685的博客-程序员秘密

技术标签: 程序员  面试  android  移动开发  

截屏2021-06-01 23.56.09.png

它最终返回一个0bservable对象,这个过程会组织网络请求、解析响应结果、将响应结果发送给订阅0bservable的0bserver

这里我们需要拆成两步来看:loadServiceMethod()、invoke()分别做了什么。

2、网络请求的准备阶段

loadServiceMethod()完成的主要任务就是解析网络请求接口方法上的注解信息,得到数据适配器、数据解析器对象,最终封装一个CallAdapted继承了ServiceMethod的对象返回来,我们来一步一步看:

截屏2021-06-01 23.56.47.png 很显然,重点是parseAnnotations():

截屏2021-06-01 23.57.41.png

RequestFactory.parseAnnotations(retrofit, method)是重要的一步,它会去解析ApiService中对应方法上的注解信息、参数上的注解信息,准备网络请求的必要信息。

接下来又调用了HttpServiceMethod的parseAnnotations(),HttpServiceMethod继承了ServiceMethod:

截屏2021-06-01 23.58.43.png 上面讲到创建retrofit对象时设置了RxJava数据适配器、Gson解析器工厂,现在要从工厂中得到对应的数据适配器、解析器,最后将这些数据封装到CallAdapted里。

HttpServiceMethod还重写了ServiceMethod的invoke()方法:

截屏2021-06-01 23.59.16.png

它的adapt方法最终调用了RxJava数据适配器的adapt()方法:

截屏2021-06-02 00.01.23.png 至此,loadServiceMethod()方法的执行流程就结束了,最终返回的就是一个继承了HttpServiceMethod的CallAdapted对象。同时准备好了 OkHttpCall、数据适配器、以及数据解析器。

3、数据适配器 结合之前的分析,调用ServiceMethod的invoke()方法最终就是调用RxJava数据适配器的adapt()方法,参数就是OkHttpCall。

数据适配器对象是通过数据适配器工厂RxJava2CallAdapterFactory创建的:

截屏2021-06-02 00.02.56.png 所以adapt()方法会返回一个Observable对象,但还是太过粗略了,我们需要进一步探究该对象的奥秘。

截屏2021-06-02 00.03.08.png 按照上边的分析,应该先执行new CallExecuteObservable<>(call),得到responseObservable对象,再执行new BodyObservable<>(responseObservable),对其进一步封装,所以我们先看CallExecuteObservable类是如何实现的:

截屏2021-06-02 00.07.41.png

截屏2021-06-02 00.07.56.png CallExecuteObservable类的核心就是subscribeActual()方法,当Observer订阅Observable时会执行该方法,即调用subscribe()方法时。 在subscribeActual()方法里会进行网络请求,并将结果传递给Observer。

那为什么BodyObservable类对responseObservable要进一步封装呢?去里边找找答案:

截屏2021-06-02 00.08.49.png

截屏2021-06-02 00.09.00.png 可以看到BodyObservable类的主要作用就是通过BodyObserver类增强我们自定义的observer功能,使其可以对CallExecuteObservable中observer.onNext(response)拿到的响应结果进一步处理,只取出响应体的数据发送给我们自定义的observer。
到这里数据适配器的主要任务就结束了,就是为整合RxJava做准备,调用Retrofit封装的OkHttpCall执行网络请求,并将结果发送给observer。
但还有些事情我们没搞清楚,那就是OkHttpCall,在CallExecuteObservable中执行它的call.execute()方法时,内部做了些什么,内部是如何通过OkHttp进行网络请求的。
4、OkHttp网络请求 OkHttpCall的execute()方法还是比较简单的:
截屏2021-06-02 00.09.44.png 所以OkHttpCall的execute()方法内部会构建OkHttp的Call对象,并来发起网络请求,但为什么是同步的请求呢?因为我们已经使用RxJava切换到子线程。这样Retrofit就和OkHttp关联上了。
5、数据解析器 OkHttpCall的parseResponse()的作用就是使用Gson将响应体的JSON字符串转换成指定对象。
![截屏2021-06-02 00.10

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

.05.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dbb13cbc9b2c4fe2ad210fb3c749591b~tplv-k3u1fbpfcp-watermark.image) 关键的就是responseConverter.convert(catchingBody),responseConverter就是通过配置Retrofit时设置的GsonConverterFactory数据解析器工厂得到的,对应的数据解析器就是GsonRequestBodyConverter:
terFactory数据解析器工厂得到的,对应的数据解析器就是GsonRequestBodyConverter:

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_65145685/article/details/121907153

智能推荐

阿里云服务器ECS 第一篇:FTP文件服务器搭建_Hello_World_QWP的博客-程序员秘密

云服务器ECS 第一篇:FTP文件服务器搭建目前打算将项目部署到云服务器上,并配置系统运行环境,搭建FTP服务器是系统部署的第一步,从这里开始!!!关于FTP:FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。基于不同的操

Windows 下单机最大TCP连接数_weixin_34247032的博客-程序员秘密

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

python中pandas下dataframe的合并方法小结_python dataframe join on_weixin_40865719的博客-程序员秘密

python中pandas是数据分析的利器,有两种基本的数据形式,Series、DataFrame两种,Series是单列的,DataFrame是平面的二维或者多维的。今天遇到一个问题,如何将两个dataFrame合并:总的来说有两种形式的合并:列名相同的合并,行名相同的合并列名相同的合并:append()函数,假设有如下数据。df = pd.DataFrame(np.random...

分布式系统中的“无状态”和“有状态”详解_有状态和无状态_禅与计算机程序设计艺术的博客-程序员秘密

有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如 tomcat 中的 session。例如登录:用户登录后,我们把登录者的信息保存在服务端 session 中,并且给用户一个 cookie 值,记录对应的 session。然后下次请求,用户携带 cookie 值来,我们就能识别到对应 session,从而找到用户的信息。

Java面试题(JUC)_ShyTan的博客-程序员秘密

JUCjava.util.concurrent的缩写线程的6种状态创建,可运行,阻塞,等待,计时等待,终结Lambda表达式java1.8之后允许接口中有部分方法的实现,需要用default关键字描述方法@FunctionalInterface 注解表示函数式接口(仅有一个抽象方法)常见异常总结ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常StackOverflowError:多线程案例

随便推点

ElasticSearch系列03:elasticsearch.yml(中文配置详解)_TURING.DT的博客-程序员秘密

一、基本配置elasticsearch的config文件夹里面有两个配置文 件:elasticsearch.yml和logging.yml,第一个是es的基本配置文件,第二个是日志配置文件,es也是使用log4j来记录日 志的,所以logging.yml里的设置按普通log4j配置文件来设置就行了。下面主要讲解下elasticsearch.yml这个文件中可配置的东西。cluster.na

MyBatis中传参时为什么要用#{}_为什么使用#}_NmzI怼怼怼的博客-程序员秘密

MyBatis中传参时为什么要用#{}  MyBatis中传参时为什么要用#{},这个问题和MyBatis如何防止SQL注入类似。不过在解释这个问题之前,先解释一下什么是SQL注入,还有些称作注入攻击这个问题。  SQL注入就是SQL对传入参数的拼接。sql语句是String类型的,如果用+来拼接,表示的是直接操作这个String类型的字符串,这是改变了sql的具体内容了,如果用#{id},表示的是操作字改变里面字段的参数值。例如:用+拼接的:"select*fromu...

小鸡拍球_小鸡运动会拍球失分_mengcc666的博客-程序员秘密

【问题描述】“蚂蚁庄园”的小鸡拍球游戏中,有三种可能的得分:5分、8分和10分。现从键盘输入一个整数的得分值,请输出该局游戏可能的得分组合。【输入形式】输入只有一行,包括一个正整数n。【输出形式】输出可能有若干行,每行是一种得分的序列,包括得5分的次数、得8分和得10分的次数,前导符和次数之间用英文冒号分隔,相邻得分次数之间用一个空格分隔。【样例输入】40【样例输出】5:0 8:0 1...

解决colab上传数据集慢的问题_colab上传数据集太慢_iddd的博客-程序员秘密

因为colab是域外的服务器,所以在国内想要上传数据集,速度是非常非常的慢,因此写下自己在解决问题时的一些方法。通过将数据集传到域外的一款软件,然后数据集传到colab我用的方法是先将数据集传到onedrive上面(放心传数据集到onedrive上面是很快的),然后将数据集通过onedrive传到谷歌云盘,然后将谷歌云盘上的数据集传到colab上。听起来很麻烦,其实很简单。第一步:登录到onedrive,然后将数据集传到文档这个文件夹下面,直接拉进去就行,必须传到文档才能进行我下面的操作。第二步

Ubuntu16.04搭建rust开发环境_菜鸟阳阳的博客-程序员秘密

Ubuntu16.04搭建rust开发环境安装vscode进入vscode官网下载Linux下的安装包,使用dpkg命令安装sudo dpkg -i code_1.37.0-1565227985_amd64.deb等待安装完成,搜索vs可以直接找到,为了方便,将其添加到启动器。如果不习惯英文,可以对vscode进行汉化,打开vscode,快捷键Shift + Ctrl + P,输入Configure Display Language进行安装即可,安装完毕需要重启vscode。安装rus

STL - 设计一个泛型算法_bailang_zhizun的博客-程序员秘密

1、需求描述v-1需求:用户给予一个整数vector,我们必须返回一个新的vector,其中内含原vector之中小于10的所有数据。根据这个需求可以很容易的设计一个如下的函数 v1_less_than_10():using vecInt = vector&lt;int&gt;;vecInt v1_less_than_10(const vecInt&amp; vec){ vecInt nVec; for (size_t ix = 0; ix &lt; vec.size(); ix++

推荐文章

热门文章

相关标签