Android开发知识学习——从Retrofit原理来看HTTP
文章目录
- Retrofit 使用方法简介
- Retrofit 源码结构总结
- 扔物线读源码的思路与方式
Retrofit 使用方法简介
- 导包
implementation 'com.squareup.retrofit2:retrofit:最新版本'
- 创建一个 interface 作为 Web Service 的请求集合,在里面用注解
(Annotation)写入需要配置的请求方法
Java代码
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Kotlin代码
interface GitHubService {@GET("users/{user}/repos")fun listRepos(@Path("user") user: String?): Call<List<Repo>>
}
- 在正式代码里用 Retrofit 创建出 interface 的实例
Java代码
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service =
retrofit.create(GitHubService.class);
Kotlin代码
//用Retrofit创建出interface的实例val retrofit: Retrofit = Retrofit.Builder().baseUrl("https://api.github.com/").build()val service:GitHubService = retrofit.create(GitHubService::class.java)
- 调用创建出的 Service 实例的对应方法,创建出相应的可以用来发起网络请求的Call 对象
Java代码
Call<List<Repo>> repos = service.listRepos("octocat");
Kotlin代码
//创建出service实例的对应方法,创建出对应的可以用来发送网络请求的call对象val repos :Call<List<Repo>> = service.listRepos("octocat")
- 使用 Call.execute() 或者 Call.enqueue() 来发起请求
Java代码
repos.enqueue(callback);
Kotlin代码
//使用 Call.execute() 或者 Call.enqueue() 来发起请求
repos.enqueue(callback);
repos.enqueue(object : Callback<List<Repo>?> {override fun onResponse(call: Call<List<Repo>?>, response: Response<List<Repo>?>) {TODO("Not yet implemented")}override fun onFailure(call: Call<List<Repo>?>, t: Throwable) {}})
Retrofit 源码结构总结
通过 Retrofit.create(Class)
方法创建出 Service interface
的实例,从
而使得 Service
中配置的方法变得可用,这是 Retrofit
代码结构的核心;
Retrofit.create()
方法内部,使用的是Proxy.newProxyInstance()
方法来创建 Service
实例。这个方法会为参数中的多个 interface
(具体到 Retrofit 来说,是固定传入一个 interface
)创建一个对象,这个对象实现了所有 interface
的每个方法,并且每个方法的实现都是雷同的:调用对象实例内部的一个 InvocationHandler
成员变量的invoke()
方法,并把自己的方法信息传递进去。这样就在实质上实现了代理逻辑:interface
中的方法全部由一个另外设定的 InvocationHandler
对象来进行代理操作。并且,这些方法的具体实现是在运行时生成 interface
实例时才确定的,而不是在编译时(虽然在编译时就已经可以通过代码逻辑推断出来)。这就是网上所说的「动态代理机制」的具体含义。
因此, invoke()
方法中的逻辑,就是 Retrofit
创建 Service
实例的关键。这
个方法内有三行关键代码,共同组成了具体逻辑:
- ServiceMethod 的创建:
loadServiceMethod(method)
这行代码负责读取 interface 中原方法的信息(包括返回值类型、方法注解、参
数类型、参数注解),并将这些信息做初步分析。实际返回的是一个
CallAdapted 。
- OkHttpCall 的创建:
new OkHttpCall<>(requestFactory, args, callFactory,
responseConverter)
OkHttpCall 是 retrofit2.Call 的子类。这行代码负责将ServiceMethod 解读到的信息(主要是一个 RequestFactory 、一个OkHttpClient 和一个 ResponseConverter )封装进 OkHttpCall ;而这个对象可以在需要的时候(例如它的enqueue() 方法被调用的时候),利用 RequestFactory 和 OkHttpClient 来创建一个 okhttp3.Call对象,并调用这个okhttp3.Call 对象来进行网络请求的发起,然后利用ResponseConverter 对结果进行预处理之后,交回给 Retrofit 的Callback 。
- adapt() 方法:
callAdapter.adapt(call);
这个方法会使用一个 CallAdapter 对象来把 OkHttpCall 对象进行转换,生成一个新的对象。默认情况下,返回的是一个 ExecutorCallbackCall ,它的作用是把操作切回主线程后再交给 Callback 。另外,如果有自定义的 CallAdapter,这里也可以生成别的类型的对象,例如RxJava 的 Observable ,来让 Retrofit 可以和 RxJava 结合使用。
- 更细的代码逻辑(例如 ServiceMethod 如何做方法解析、CallAdapter 如何做adapt,就不在讲义里再总结一遍了,可以看课上的分析)
扔物线读源码的思路与方式
-
寻找切入点,而不是逐行通读
- 理想情况下,逐行通读可以最高效率读通一个项目的代码,因为每行代码都只需要读一遍;但实时情况下,逐行通读会导致脑中积累太多没有成体系的代码,导致你读个几十几百行就读不下去了,因此一点也不实用。而从切入点开始读,可以在最快时间内把看到的代码体系化,形成一个「完整的小世界」;在把「小世界」看明白之后,再去一步步扩大和深入,就能够逐渐掌握更多的细节。
- 寻找切入点的方式:离你最近的位置就是切入点,通常是业务代码中的最后一行。
- 以 Retrofit 为例,最后的 Call.enqueue() 会被我作为切入点;在尝试从 Call.enqueue() 切入失败后,逐步回退到 Retrofit.create()方法,找到项目结构的核心,然后开始继续发散和深入。
-
在阅读过程中,始终保有把看过的代码逻辑完整化的意识
- 代码阅读过程中,不懂的代码会越来越多,脑子就会越来越乱。如果不断尝试把看到的代码结合起来组合成完整逻辑,就能让头脑始终保持清晰,而不是深入到某个细节好久之后忽然一抬头:「我为什么点进这个方法来着?」可以试着在读源码的时候,经常把多行或多段代码在脑子里(或者笔记里)
组合成一整块,从而让代码结构更清晰,让阅读过程不断增加进度感,也减小继续阅读的难度。 - 以 Retrofit 为例,当读懂 Proxy.newProxyInstance() 方法实际上是创建了一个代理对象的时候,可以停下来做一个总结:「这是 Retrofit 的大框架」,在脑子里或者笔记上都可以。总结消化过后,再继续阅读。
- 代码阅读过程中,不懂的代码会越来越多,脑子就会越来越乱。如果不断尝试把看到的代码结合起来组合成完整逻辑,就能让头脑始终保持清晰,而不是深入到某个细节好久之后忽然一抬头:「我为什么点进这个方法来着?」可以试着在读源码的时候,经常把多行或多段代码在脑子里(或者笔记里)
-
尽量让每一刻都有一个确定的目标
- 读代码经常会出现「横向逻辑还没看清晰,纵向深度也没挖透」的情况。那么到底是要横向扩展阅读结构,还是纵向挖深度,最好是在每次遇到这种分岔路口的时候就先做好决定。不能在每个分岔路口都想也不想地看到不懂的就追下去,容易迷路。
- 在遇到「横向也广,纵向也深」的时候,根据情况选择其中一个就好,并没有必然哪种选择更优的铁律。而如果遇到越钻越头大的情况,可以退回之前的某一步,换条路继续走。换路的时候记得做好标记:「我在哪里探路失败了」。
相关文章:

Android开发知识学习——从Retrofit原理来看HTTP
文章目录 Retrofit 使用方法简介Retrofit 源码结构总结扔物线读源码的思路与方式 Retrofit 使用方法简介 导包 implementation com.squareup.retrofit2:retrofit:最新版本创建一个 interface 作为 Web Service 的请求集合,在里面用注解 (Annotation&…...

计算机毕设 基于大数据的抖音短视频数据分析与可视化 - python 大数据 可视化
文章目录 0 前言1 课题背景2 数据清洗3 数据可视化地区-用户观看时间分界线每周观看观看路径发布地点视频时长整体点赞、完播 4 进阶分析相关性分析留存率 5 深度分析客户价值判断 5 最后 0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,…...
1.OpenResty系列之入门简介
OpenResty(也称为ngx_openresty)是一个基于Nginx的全功能Web应用服务器,它将Nginx与一组附加模块和Lua脚本语言集成在一起,以提供高性能的Web应用程序开发和扩展性。 Nginx是一个轻量级的、高性能的HTTP服务器和反向代理服务器&a…...
Trie树(字典树)
原理: 1. ch[p][j]:p是每个单词存到的idx索引,j是存入字符映射的数字 2. cnt[p] 存这个单词个数 【模板】字典树 - 洛谷 #include <iostream> #include <cstring> using namespace std;const int N 3e6 10; int ch[N][100], idx; int cnt…...
华为政企网络安全产品集
产品类型产品型号产品说明 防火墙及应用安全网关ASG5505ASG5000系列上网行为管理产品(以下简称“ASG5000”)是华为面向各类企业、政府、大中型数据中心以及各类无线非经营性场所推出的业界领先的综合上网行为管理产品。 该系列产品可深度识别、管控和…...
02-Sping事务实现之声明式事务基于XML的实现方式
声明式事务之XML实现方式 开发步骤 第一步: 引入AOP相关的aspectj依赖 <!--aspectj依赖--> <dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.0-M2</version> <…...

桶装水订水系统水厂送水小程序开发;
桶装水小程序正式上线,支持多种商品展示形式,会员卡、积分、分销等功能; 开发订水送水小程序系统,基于用户、员工、商品、订单、配送站和售后管理模块,对每个模块进行统计分析,简化了分配过程,提…...
png或jpg等图片文件转ico图标文件,格式在线转换
图片文件转ico图标文件在线转换:在线转换图片格式-在线图片转换器-100% 免费 (jinaconvert.com)...

操作系统——对文件的 基本操作(王道视频p65)
1.总体概述: 2.进程打开文件表 和 系统打开文件表:...

中海达守护电力人员作业安全
近日,中海达为电网某换流站作业人员提供的160余套北斗高精度定位产品顺利完成交付。通过使用北斗高精度定位技术,帮助换流站实现了人员(车辆)位置实时定位、电子围栏实时预警、远程作业指导等应用效果,用高科技保障电网…...

想学计算机编程从什么学起?零基础如何自学计算机编程?中文编程开发语言工具箱之渐变标签组构件
想学计算机编程从什么学起?零基础如何自学计算机编程? 给大家分享一款中文编程工具,零基础轻松学编程,不需英语基础,编程工具可下载。 这款工具不但可以连接部分硬件,而且可以开发大型的软件,…...

中国人民大学与加拿大女王大学金融硕士——一把开启未来金融世界的金钥匙
在这个日新月异、竞争激烈的时代,每个人都渴望不断提升自我,以应对不断变化的世界。在当今的金融领域,国际化的视野和多元化的知识结构变得越来越重要。如何才能掌握未来世界的金钥匙呢?其实,这把金钥匙并非遥不可及&a…...

MVC、MVP、MVVM区别
MVC、MVP、MVVM区别 MVC(Model-View-Controller) 。是一种设计模式,通常用于组织与应用程序的数据流。它通常包括三个组件:模型(Model)、视图(View)和控制器(Controller&…...

【Kotlin精简】第7章 泛型
1 泛型 泛型即 “参数化类型”,将类型参数化,可以用在类,接口,函数上。与 Java 一样,Kotlin 也提供泛型,为类型安全提供保证,消除类型强转的烦恼。 1.1 泛型优点 类型安全:通用允许…...

ElasticSearch与Lucene是什么关系?Lucene又是什么?
一. ElasticSearch 与 Lucene 的关系 Elasticsearch(ES)和Apache Lucene之间有密切的关系,可以总结如下: Elasticsearch构建于Lucene之上:Elasticsearch实际上是一个分布式的、实时的搜索和分析引擎,它构建…...

【算法练习Day40】打家劫舍打家劫舍 II打家劫舍 III
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:练题 🎯长路漫漫浩浩,万事皆有期待 文章目录 打家劫舍打家劫舍 II打家劫…...

双十一运动健身好物推荐,这几款健身好物一定不要错过!
双十一购物狂欢节又要到了,又要到买买买的时候了!相信有很多想健身的小白还在发愁不知道买啥装备?别急,三年健身达人这就给你们分享我的年度健身好物! 第一款:南卡Runner Pro4s骨传导耳机 推荐理由&#…...

Angular异步数据流编程
1 目前常见的异步编程的几种方法 首先给出一个异步请求的实例: import {Injectable} from angular/core;Injectable({providedIn: root }) export class RequestServiceService {constructor() {}getData() {setTimeout(() > {let res zhaoshuai-lcreturn res…...

古典舞学习的独舞与群舞,古典舞的成品舞蹈教学大全
一、教程描述 本套教程的古典舞是很全面的,不仅有舞蹈动作分解教学,而且有成品舞的完整教学,同时提供独立的背景音乐文件,可以让你更快地学会古典舞。本套教程,大小30.54G,共有276个文件。 二、教程目录 …...

听GPT 讲Rust源代码--library/std(16)
题图来自 EVALUATION OF RUST USAGE IN SPACE APPLICATIONS BY DEVELOPING BSP AND RTOS TARGETING SAMV71[1] File: rust/library/std/src/sync/mpmc/select.rs 在Rust标准库中,rust/library/std/src/sync/mpmc/select.rs文件的作用是实现一个多生产者多消费者的选…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...