Android开发知识学习——从Retrofit原理来看HTTP

文章目录

  • Retrofit 使用方法简介
  • Retrofit 源码结构总结
  • 扔物线读源码的思路与方式

Retrofit 使用方法简介

  1. 导包
  implementation 'com.squareup.retrofit2:retrofit:最新版本'
  1. 创建一个 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>>
}
  1. 在正式代码里用 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)
  1. 调用创建出的 Service 实例的对应方法,创建出相应的可以用来发起网络请求的Call 对象
    Java代码
Call<List<Repo>> repos = service.listRepos("octocat");

Kotlin代码

//创建出service实例的对应方法,创建出对应的可以用来发送网络请求的call对象val repos :Call<List<Repo>> = service.listRepos("octocat")
  1. 使用 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 实例的关键。这
个方法内有三行关键代码,共同组成了具体逻辑:

  1. ServiceMethod 的创建:
loadServiceMethod(method)

这行代码负责读取 interface 中原方法的信息(包括返回值类型、方法注解、参
数类型、参数注解),并将这些信息做初步分析。实际返回的是一个
CallAdapted 。

  1. 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 。

  1. 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 的大框架」,在脑子里或者笔记上都可以。总结消化过后,再继续阅读。
  • 尽量让每一刻都有一个确定的目标

    • 读代码经常会出现「横向逻辑还没看清晰,纵向深度也没挖透」的情况。那么到底是要横向扩展阅读结构,还是纵向挖深度,最好是在每次遇到这种分岔路口的时候就先做好决定。不能在每个分岔路口都想也不想地看到不懂的就追下去,容易迷路。
    • 在遇到「横向也广,纵向也深」的时候,根据情况选择其中一个就好,并没有必然哪种选择更优的铁律。而如果遇到越钻越头大的情况,可以退回之前的某一步,换条路继续走。换路的时候记得做好标记:「我在哪里探路失败了」。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/182196.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

修复RGBA的png为RGB的png

修改IHDR里面的color type 修改IHDR的crc 删除sBit和sRGB两个chunk

设置Linux时间格式

一、事因 不知道什么时候我在输入ls -l 命令时候的显示变成了。 -rw-r--r-- 1 bossftp ftp 6796376499 915 05:31 rac_full_20230915.gz -rw-r--r-- 1 bossftp ftp 6804104515 104 05:25 rac_full_20231024.gz -rw-r--r-- 1 bossftp ftp 6804365525 105 05:29 rac_full_202…

开源六轴协作机械臂MechArm 拖动示教模型案例

介绍 今天&#xff0c;我将向大家展示一个我独立设计并实现的机械臂模型。这个模型的核心功能是实现实时的手势追踪——只需用手轻轻拖拽&#xff0c;机械臂就能立即跟随你的动作进行移动。 我之所以想要创造这样一个模型&#xff0c;是因为在一些危险环境中&#xff0c;我们可…

【缓存】Spring全家桶中@CacheEvict无效情况共有以下几种

Spring全家桶中CacheEvict无效情况共有以下几种 一、背景介绍二、原因分析三、解决方案 一、背景介绍 SpringBoot中使用Cacheable注解缓存数据&#xff0c;使用CacheEvict注解删除缓存。但是在项目使用过程中&#xff0c;发现使用CacheEvict注解删除缓存无效。 拓展&#xff…

软件测试需不需要懂代码?

无论是刚入测试行业的萌新&#xff0c;还是已经在测试行业闯荡了两三年的小司机们&#xff0c;都会琢磨一个问题&#xff1a;如果要持续发展下去&#xff0c;我要不要懂代码&#xff1f; 在软件测试初级阶段&#xff0c;不需要编程能力。但是任何一个职业&#xff0c;都会追求…

【ubuntu】搭建lamp架构

一、准备工作 1、更新源 apt-get updateapt #就是一个管理包的工具&#xff0c;理解为centos中的yum update #表示让apt执行更新的操作&#xff0c;更新的内容为软件列表。#为什么要更新软件列表&#xff1f; 就时本地会隔断时间进行同步镜像站的资源包&#xff0c;但是我…

vue3+ts 项目遇到的问题和bug

1.router中使用pinia报错 pinia.mjs:1709 Uncaught Error: [&#x1f34d;]: "getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"? See https://pinia.vuejs.org/core-concep…

MySQL(9):子查询

子查询 指一个查询语句嵌套在另一个查询语句内部的查询&#xff0c;这个特性从MySQL 4.1开始引入。 SQL 中子查询的使用大大增强了 SELECT 查询的能力&#xff0c;因为很多时候查询需要从结果集中获取数据&#xff0c;或者需要从同一个表中先计算得出一个数据结果&#xff0c;…

FIddler抓手机的通讯包的设置记录

今天不知怎么滴&#xff0c;想用电脑的fiddler抓取手机的通讯过程了&#xff0c;记得原来我是会的&#xff0c;但是当时没有记录&#xff0c;所以都忘了&#xff0c;今天有空在重新来一遍&#xff0c;把过程记录一下&#xff0c;省的下次在记不住了&#xff0c;还有地方查&…

软件测试具体人员分工

最近看了点敏捷测试的东西&#xff0c;看得比较模糊。一方面是因为没有见真实的环境与流程&#xff0c;也许它跟本就没有固定的模式与流程&#xff0c;它就像告诉人们要“勇敢”“努力”。有的人在勇敢的面对生活&#xff0c;有些人在勇敢的挑战自我&#xff0c;有些人在勇敢的…

辐射骚扰整改思路及方法:辐射超标与问题定位 ?

某产品首次EMC测试时&#xff0c;辐射、静电、浪涌均失败。本篇文章就“辐射超标与问题定位”问题进行详细讨论。 一、辐射超标 50MHz 、100MHz 、130MHz 、200MHz&#xff0c;4个频点明显超标&#xff0c;其中130MHz 左右最明显&#xff0c;超出 19dB&#xff1b;后将电路板…

聊一聊关于手机Charge IC的电流流向

关于手机Charge&#xff0c;小白在以前的文章很少讲&#xff0c;一是这部分东西太多&#xff0c;过于复杂。二是总感觉写起来欠缺点什么。但后来想一想&#xff0c;本是抱着互相学习来写文章的心理态度&#xff0c;还是决定尝试写一些。 关于今天要讲的关于手机Charge的内容&a…

未来已来!2023 云栖大会龙蜥操作系统专场精彩回顾

2023 云栖大会龙蜥操作系统专场&#xff08;以下简称为“专场”&#xff09;圆满落幕。本次专场特别邀请到开放原子开源基金会理事长孙文龙和中国信息通信研究院副总工程师石友康莅临指导&#xff0c;现场聚集了阿里云、统信软件、浪潮信息、Intel、Arm、麒麟软件、蚂蚁集团、中…

智慧公厕:科技赋予公共卫生新生命,提升城市管理品质

在现代化城市中&#xff0c;公共卫生设施的发展与提升一直是对城市管理者和市民的共同期望。然而&#xff0c;传统的公共厕所常常令人困扰&#xff0c;脏乱臭成为难题。为了解决这一难题&#xff0c;广州中期科技科技有限公司全新升级的智慧公厕整体解决方案&#xff0c;补誉为…

椭圆滤波器

之前的文章 信号去噪 中列出了7种常用的信号去噪算法&#xff0c;对于后两种算法——深度学习和奇异值分解(SVD)&#xff0c;我现在也不太理解&#xff0c;就先不写了。 很多朋友留言又提了一些算法&#xff0c;今天一起来聊聊椭圆滤波器。 椭圆滤波器&#xff08;Elliptic F…

diffusers-Tasks

https://huggingface.co/docs/diffusers/using-diffusers/unconditional_image_generationhttps://huggingface.co/docs/diffusers/using-diffusers/unconditional_image_generation1.Unconditional image generation 无条件图像生成是一个相对简单的任务。模型仅生成图像&…

python基础速通

1. 梳理&#xff1a;目前学习了哪几种数据类型&#xff0c; 每一个数据类型定义一个变量&#xff0c;并输出内容以及类型 # 数据类型 # 整型 int_data 1 print(int_data, type(int_data)) # 浮点型 float_data 1.2 print((float_data, type(float_data))) # 复数 complex_da…

【LeetCode每日一题合集】2023.9.18-2023.9.24(⭐拓扑排序⭐设计数据结构:LRU缓存实现 LinkedHashMap⭐)

文章目录 337. 打家劫舍 III&#xff08;树形DP&#xff09;2560. 打家劫舍 IV&#xff08;二分查找动态规划&#xff09;LCP 06. 拿硬币&#xff08;简单贪心模拟&#xff09;2603. 收集树中金币⭐思路——拓扑排序删边 2591. 将钱分给最多的儿童&#xff08;分类讨论&#xf…

一份优秀测试用例的设计策略

日常工作中最为基础核心的内容就是设计测试用例&#xff0c;什么样的测试用例是好的测试用例?我们一般会认为数量越少、发现缺陷越多的用例就是好的用例。那么我们如何才能设计出好的测试用例呢&#xff1f;一份好的用例是设计出来的&#xff0c;是测试人员思路和方法的集合&a…

数字博物馆如何设计搭建,一文了解数字博物馆解决方案

导言&#xff1a; 数字博物馆是一种创新性的文化机构&#xff0c;通过数字技术的应用&#xff0c;将传统博物馆的宝贵文化遗产以全新的方式呈现给观众。 一.数字博物馆是什么 博物馆是指利用数字技术和互联网等新媒体技术来展示和传播文物、艺术品等文化遗产的博物馆。数字物…