Android Retrofit框架分析(三):自动切换回主线程;bulid的过程;create方法+ServiceMethod源码了解

目录

  1. Okhttp有什么不好?
  2. bulid的过程
  3. create方法+ServiceMethod
  4. call + enqueue的过程
  5. 为什么要学习源码呢?

一、Okhttp有什么不好?

Okhttp本身来说,是一个挺好的网络框架,但,对于开发者而言,使用起来,会过于繁琐。下面我们看看一个代码:

// 1️⃣ 手动拼接URL和参数(容易出错)
HttpUrl url = HttpUrl.parse("https://api.example.com/user").newBuilder().addQueryParameter("id", "123").build();// 2️⃣ 创建请求对象
Request request = new Request.Builder().url(url).build();// 3️⃣ 发起异步请求
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {// 4️⃣ 手动解析JSON(容易遗漏判空)String json = response.body().string();User user = new Gson().fromJson(json, User.class);// 5️⃣ 手动切回主线程更新UI(忘记切换会崩溃)runOnUiThread(() -> {textView.setText(user.getName());});}@Overridepublic void onFailure(Call call, IOException e) {// 6️⃣ 手动处理失败逻辑(比如Toast错误)}
});

​问题总结​​:

  • ​代码臃肿​​:每个请求都要写重复代码(拼参数、解析JSON、线程切换)。
  • ​维护困难​​:如果接口路径或参数变更,需要全局搜索修改。
  • ​容错成本高​​:手动处理空指针、JSON解析异常、线程安全问题。

下面我们看看Retrofit的代码:

// 1️⃣ 声明接口(像写文档一样直观)
public interface ApiService {@GET("user")Call<User> getUser(@Query("id") String id); // 自动拼接参数
}// 2️⃣ 发起请求(3行代码搞定)
ApiService service = retrofit.create(ApiService.class);
service.getUser("123").enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {// ✅ 自动解析JSON → User对象// ✅ 自动切回主线程textView.setText(response.body().getName());}
});

优化原理​​:

  • ​声明式API​​:用注解代替手动拼参数(如@GET定义接口路径,@Query自动拼接URL参数)。
  • ​自动解析​​:通过GsonConverter直接将JSON转成User对象。
  • ​线程安全​​:回调时自动切换回主线程(背后是MainThreadExecutor)。

那么他是如何做到的呢?接下来,我们看看源码。


二、bulid的过程

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/")  // 必填:API根路径.client(new OkHttpClient())          // 选填:自定义OkHttp(比如加日志拦截器).addConverterFactory(GsonConverterFactory.create()) // 选填:数据解析器.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 选填:适配RxJava.build();

这个主要是做什么?可以理解为就是将所需的参数全部保存起来,方便后面使用,比如url,数据解析器等,都是为后面发起请求,和接收响应进行使用,使用bulid构建一个Retrofit,这就是bulid的作用。我们可以进入他的源码看看:

比如addConverterFactory以及addCallAdapterFactory方法,都是使用List来保存起来,

在这里插入图片描述

url也是

在这里插入图片描述

然后使用bulid构建一个Retrofit。

在这里插入图片描述

建造过程核心逻辑​​:

  1. ​校验必填参数​​:比如baseUrl不能为空。
  2. ​设置默认组件​​:如果没配置CallAdapter,默认用ExecutorCallAdapterFactory(处理主线程回调)。
  3. ​组合所有配置​​:将ConverterCallAdapter等组件打包到Retrofit对象中。

三、create方法+ServiceMethod

// 1️⃣ 声明接口(像写文档一样直观)
public interface ApiService {@GET("user")Call<User> getUser(@Query("id") String id); // 自动拼接参数
}// 2️⃣ 发起请求(3行代码搞定)
ApiService service = retrofit.create(ApiService.class);
service.getUser("123");

当我们调用retrofit.create方法的时候,我们看看内部做了什么。

在这里插入图片描述

通过 Proxy.newProxyInstance 创建接口的代理对象,那么当我们调用service.getUser(“123”)的时候,代理对象的所有方法调用都会路由到 InvocationHandler.invoke()。让所有的接口都走 invoke函数,这样就可以拦截调用函数的执行,从而将网络接口的参数配置归一化。这个invoke方法,就是典型的AOP思想,在中间切开一个口。

invoke函数是如何完成网络请求,从这个retrofit到okhttp呢?

接下来,我们看看loadServiceMethod方法

在这里插入图片描述

这个方法返回了一个ServiceMethod,这里面主要做了什么?解析方法上的 @GET@POST 等注解,解析 @Query@Path@Body 等参数注解,解析结果会被缓存到 serviceMethodCache 避免重复解析。

每个接口方法(如 getUser())首次调用时都会生成专属的 ServiceMethod,即使同一个接口中的不同方法(如 getUser()login()),也会生成不同的 ServiceMethod,然后通过 serviceMethodCache 的 ConcurrentHashMap 缓存起来,Key 为 Method 对象。


四、call + enqueue的过程

那么接口方法上的所有信息,参数都已经拿到了,也解析好了,接下来干嘛?我们继续看回源码这里,会调用invoke方法。

在这里插入图片描述
在这里插入图片描述

创建 OkHttpCall 对象,通过传递进来的参数,json解析成对应的bean,返回封装了okhttp的call
在这里插入图片描述

在这里插入图片描述

call有了以后,接下来就是调用enqueue方法

在这里插入图片描述

在得到response以后,要返回给主线程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

底层还是handler。


五、为什么要学习源码呢?

一开始的时候,在想,为什么要看源码,看了源码以后,你了解他的原理,你也可以运用他的技术,用到其他方面,比如注解的使用,动态代理的使用。

然后也能了解他的底层逻辑,后面我们写retrofit代码的时候,也会有一种恍然大悟的感觉,比如回调的这个地方,已经自动会切换到主线程。

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

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

相关文章

C++ STL 基础与多线程安全性说明文档

C STL 基础与多线程安全性说明文档 一、STL 简介 STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是 C 标准库的重要组成部分&#xff0c;提供了常用的数据结构和算法的泛型实现&#xff0c;极大地提高了代码的复用性和开发效率。 STL 的六大组…

数据结构之图的分类和存储

图 图(Graph)G由两个集合V和E组成&#xff0c;记为&#xff1a;G(V,E)&#xff0c;其中V是顶点的有穷非空集合(其实就是顶点)&#xff0c;E是V 中顶点偶对的有穷集合(就是边)。V(G)和E(G)通常分别表示图G的顶点集合以及边集合&#xff0c;E(G)可以为空集合&#xff0c;但是此时…

扩增子分析|微生物生态网络稳定性评估之鲁棒性(Robustness)和易损性(Vulnerability)在R中实现

一、引言 周集中老师团队于2021年在Nature climate change发表的文章&#xff0c;阐述了网络稳定性评估的原理算法&#xff0c;并提供了完整的代码。自此对微生物生态网络的评估具有更全面的指标&#xff0c;自此网络稳定性的评估广受大家欢迎。本系列将介绍网络稳定性之鲁棒性…

setup 函数在 Vue 3 中的作用是什么?什么时候会执行

文章目录 前言✅ 一、setup() 函数的作用是什么&#xff1f;✅ 二、setup() 什么时候执行&#xff1f;✅ 三、setup() 的参数✅ 四、setup() 中不能做什么&#xff1f;✅ 五、常见用法示例✅ 六、总结&#xff08;适合背诵或面试回答&#xff09; <script setup> 是 **Vu…

JDBC实现--保姆级教程~

本来以为写过一个使用python与数据库连接的文章&#xff0c;但是今天突然发现没有&#xff0c;那就直接写Java与数据库连接的吧。当然如果大家有需要可以告诉我&#xff0c;有时间的话也可以写一个的pymysql的使用的。 数据库有很多种&#xff0c;接下来我就以MySQL为例来进行讲…

Ubuntu18.04搭建samda服务器

一.什么是Samba服务器&#xff1f; Samba服务器是一种基于开源协议实现的网络共享服务软件&#xff0c;主要用于在不同操作系统&#xff08;如Windows、Linux、Unix&#xff09;之间实现文件和打印机共享功能。其核心目标是解决跨平台资源共享的兼容性问题&#xff0c;尤其是在…

《分词算法大揭秘:BPE、BBPE、WordPiece、ULM常见方法介绍》

分词算法是自然语言处理&#xff08;NLP&#xff09;中的一个重要预处理步骤&#xff0c;它将文本分割成更小的单元&#xff08;如单词、子词或字符&#xff09;。以下是几种常见的分词算法&#xff1a;Byte Pair Encoding (BPE)、Byte-level BPE (BBPE)、WordPiece 和 Unigram…

WordPress01 - 后台常用功能

最近些日子研究Wordpress&#xff0c;做些简单的笔记。 怎么安装Wordpress&#xff0c;怎么进的后台&#xff0c;这些咱就不唠了哈&#xff0c;网上到处是教程。 目录 1&#xff0c;Wordpress的后台 1-1&#xff0c; Posts(投稿) 1-2&#xff0c;Media(媒体) 1-3&#xf…

R8周:RNN实现阿尔茨海默病诊断

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 一、前期准备 1.设置GPU import numpy as np import pandas as pd import torch from torch import nn import torch.nn as nn import torch.nn.functi…

今天python练习题

目录 一、每日一言 二、练习题 三、效果展示 四、下次题目 五、总结 一、每日一言 不要害怕失败&#xff0c;失败可能成为我们前进的动力&#xff01; 二、练习题 有列表lst [[1,2,3],[4,5,6],[7,8,9]],取出其中的元素1/5/9组成新的列表 # 有列表lst [[1,2,3],[4,5,6],[…

机器人强化学习入门学习笔记(二)

基于上一篇的《机器人强化学习入门学习笔记》,在基于 MuJoCo 的仿真强化学习训练中,除了 PPO(Proximal Policy Optimization)之外,还有多个主流强化学习算法可用于训练机器人直行或其他复杂动作。 🧠 一、常见强化学习算法对比(可用于 MuJoCo) 算法类型特点适合场景PP…

用 DuckDB 高效分析 JSON 数据:从入门到实战

解析 JSON 文件进行分析常常充满挑战。无论你是在处理 API 响应、日志文件&#xff0c;还是应用数据&#xff0c;如果没有合适的工具&#xff0c;分析 JSON 都会非常耗时。 借助 DuckDB&#xff0c;你可以直接用 SQL 查询复杂的 JSON 文件&#xff0c;无需编写复杂的解析代码或…

从贴牌到品牌:出海官网如何让中国制造“贵”起来?

在全球经济一体化的当下&#xff0c;中美关税战如同一记重锤&#xff0c;给国际贸易格局带来了巨大震荡。自贸易摩擦爆发以来&#xff0c;双方多次调整关税政策&#xff0c;涉及的商品种类不断增多&#xff0c;税率持续攀升&#xff0c;众多中国企业的出口业务遭受重创&#xf…

react-13react中外部css引入以及style内联样式(动态className与动态style)

1. 外部css文件 - 普通引入 1.1 创建一个 CSS 文件&#xff0c;MyComponent.css。 /* MyComponent.css */ .my-class {color: red;font-size: 20px; } 1.2 组件中import引入 import React from react; import ./MyComponent.css; // 引入 CSS 文件function MyComponent() {r…

n8n 与智能体构建:开发自动化 AI 作业的基础平台

n8n 是一款开源的自动化流程构建平台&#xff0c;通过其模块化节点系统&#xff0c;开发者可以快速实现跨平台的任务编排、数据集成与智能交互。当 n8n 与大型语言模型&#xff08;LLM&#xff09;结合时&#xff0c;就能构建出具备感知、推理、执行能力的 AI 智能体&#xff0…

14.Spring Boot 3.1.5 集成 Spring Security 进行访问控制

14.Spring Boot 3.1.5 集成 Spring Security 进行访问控制 Spring Security 是一个强大且高度可定制的认证和访问控制框架&#xff0c;专为基于 Spring 的应用程序设计。它为基于 Java EE 的企业应用程序提供了全面的安全解决方案&#xff0c;包括 Web 应用程序安全和方法级安…

Linux学习笔记(二):Linux权限管理

文章目录 一、Linux下用户的分类1. Linux下用户分为两类&#xff1a;2. 这两类用户如何进行切换呢&#xff1f;3. 短暂提权 二、何为权限1. 什么是权限2. Linux的文件后缀意义 三、修改权限1. 设置文件的访问权限——chmod2. 修改文件拥有者——chown3. 修改文件所属组——chgr…

学习alpha,第2个alpha

alphas (-1 * ts_corr(rank(ts_delta(log(volume), 2)), rank(((close - open) / open)), 6)) 先分析操作符从左到右 ts_corr: Pearson 相关度量两个变量之间的线性关系。当变量呈正态分布且关系呈线性时&#xff0c;它最有效。 ts_corr(vwap, close, 20)是一个计算时间序列相…

Paddle Serving|部署一个自己的OCR识别服务器

前言 之前使用C部署了自己的OCR识别服务器&#xff0c;Socket网络传输部分是自己写的&#xff0c;回过头来一看&#xff0c;自己犯傻了&#xff0c;PaddleOCR本来就有自己的OCR服务器项目&#xff0c;叫PaddleServing&#xff0c;这里记录一下部署过程。 1 下载依赖环境 1.1 …

React Native【详解】搭建开发环境,创建项目,启动项目

下载安装 node https://nodejs.cn/download/ 查看 npx 版本 npx -v若无 npx 则安装 npm install -g npx创建项目 npx create-expo-applatestRN_demo 为自定义的项目名称 下载安装 Python 2.7 下载安装 JAVA JDK https://www.oracle.com/java/technologies/downloads/#jdk24-…