!!!解决Retrofit多BaseUrl及运行时动态改变BaseUrl?

Retrofit动态更换BaseUrl最后的妥协 Retrofit动态更换BaseUrl最后的妥协 最近接到一个需求,要让我们的app可以在测试环境和正式环境间随意切换(PS:测试环境的域名多种多样)。本来是一件特简单的事情,但是由于开发和维护Retrofit的大佬们觉得动态替换BaseUrl不安全,使得这件事情变得复杂起来。经过搜索资料以及查看源码,整理出来解决方案有如下几种。 1、更新Retrofit对象 本来项目里面是全局保存着一... 阅读详情

前言

Hello,我是 JessYan,作为一个喜欢探索新颖解决方案的我,在 上篇文章 中,向大家介绍了怎样通过一行代码即可实现上传下载以及 Glide 进度监听,现在又给大家带来了另一项大家都很期待的问题的解决方案,这个问题起源于 MVPArms 的一个 Issues ,当然使用 Retrofit 时,多个 BaseUrl 以及动态切换 BaseUrl 这两个需求,在其他地方也经常被讨论,那么下面就来讲讲我的思路和解决方案

Github : 你的 Star 是我坚持的动力 ✊

gif

需求出现的场景

也许在日常开发中有些人已经遇到了这两个需求的场景,但为了让一些之前没遇到这些场景的朋友,也能看懂这篇文章,所以先在前面提一提

多个 BaseUrl 的需求场景

如果项目是聚合型 App ,比如像一些新闻资讯类客户端,可能数据源来自于多个平台,比如说知乎啊,豆瓣啊,今日头条啊,所以这样就会涉及到多个 BaseUrl

如果项目使用到多个三方服务提供商,比如图片的读取使用到一个服务商,文件的存储又使用到另一个服务商,这个也会存在一个 App 出现多个 BaseUrl

动态改变 BaseUrl 的需求场景

如果项目的 BaseUrl 会在 App 启动时,请求服务器,根据服务器的返回结果,来确定项目最终的 BaseUrl,就会涉及到运行时动态切换 BaseUrl

如果项目的某个三方服务提供商,并不是固定的,也许会出现变更的情况,比如存储服务从七牛迁移至其他云存储,那我们为了避免更改代码导致重新打包以及发版,就会从服务器获取三方服务提供商的 BaseUrl ,然后在运行时动态改变这个 BaseUrl

解决方案

其实官方 Api 早已经提供了解决方案来支持多个 BaseUrl 以及运行时动态改变 BaseUrl ,民间也同样有很多解决方案

官方静态解决方案

熟悉 Retrofit 的开发者应该知道 @Get , @Post 这些标注到每个接口方法上的注解不仅可以传相对路径,还可以传全路径,这样我们就可以做到不同的接口使用不同的 BaseUrl ,从而达到使用多个 BaseUrl 的需求,但是注解上的值只能是 Final 的常量,不能动态改变,所以我称这个解决方案为静态解决方案

官方动态解决方案

熟悉 Retrofit 的开发者也同样知道 @Url 这个标注到每个接口方法参数上的注解,它可以将全路径作为参数传进接口作为每次请求的 Url 地址,每次请求接口都可以将不同的全路径作为参数,从而达到支持多个 BaseUrl 以及在运行时动态改变 BaseUrl ,所以很多请求图片等资源的接口都是使用这个方案(咦,看样子这个官方解决方案不是同时解决我提到的这两个问题吗,别急,先往后面看!)

民间常用解决方案

之前也看过很多开源的聚合类 App 源码,像一些整合 知乎 , 豆瓣 , Gank 等多个平台数据的 App ,因为各自平台的域名不同,所以大多数这类 App 会给每个平台都各自创建一个 Retrofit 对象,即不同的 BaseUrl 使用不同的 Retrofit 对象来创建 ApiService 进行请求,这样只要新增一个不同的 BaseUrl ,那就需要重新创建一个新的 Retrofit 对象

这样也可以同时实现,支持多个 BaseUrl 以及运行时动态改变 BaseUrl 这两个需求,但是以个人的观点,创建多个其他配置属性一模一样,只是 BaseUrl 不一样的 Retrofit 对象,太过于浪费资源

民间大牛解决方案

之前偶然看到了一个 Retrofit 维护者, Square 公司的大牛的 解决方案,用来解决运行时动态改变 BaseUrl ,其实也算半官方的解决方案

提到这个解决方案时,不得不讲一个趣事,其实之前 Retrofit 默认是支持运行时动态改变 BaseUrl 的,以前是有一个名为 BaseUrl 的接口,而 Retrofit.Builder#baseUrl(BaseUrl) 方法当时传的参数就是这个 BaseUrl ,而不是现在的 HttpUrl ,这个接口内部就有一个方法返回 HttpUrl ,那时候只要实现 BaseUrl 后,动态改变这个方法的返回值,就可以实现动态改变 BaseUrl

但是这位大牛认为这样的做法不安全,所以提了一个 Pull Requests ,删掉了这个 BaseUrl 接口,并用上面的解决方案替代之,而亲爱的 JakeWharton 同意了他的观点,并合并了这个 PR 于是才有了现在的 Retrofit.Builder#baseUrl(HttpUrl) 这个不能动态改变 BaseUrl 的 Api

用 Retrofit 比较早的老鸟,应该知道以前有一个这个 Api,我是说后来的版本怎么没了,原来毁在了这位兄台手上

这个方案也就是利用 Interceptor 拦截器,动态改变每个 Request 的 Url 从而实现动态改变 BaseUrl,但他这个解决方案不能支持多 BaseUrl ,只要 host 一设置,直到下一次改变 Host 之前,后面的所有 Request 都必须使用同一个 Host ,还有一些弊端后面一起分析

几个方案的对比与分析

淘汰含有明显缺陷的方案

4个方案中,我首先淘汰的就是 民间常用解决方案 ,在前面已经明确了我的观点,因为我个人认为创建多个其他配置属性一模一样,只是 BaseUrl 不一样的 Retrofit 对象,太过于浪费资源,所以就算他能满足我的所有需求,除非真的没有更好的解决方案,否则我是不会选择它的

剩下的三个方案中, 官方静态解决方案 只能解决,2个需求中的支持多个 BaseUrl ,而对于动态改变 BaseUrl ,由于注解的 Value 只能为常量,所以对这个需求也是无能为力的(两个需求都满足,才表示可行)

谁是最优方案?

其实在前面已经说了 官方动态解决方案 就已经可以同时实现多 BaseUrl 和运行时动态改变 BaseUrl ,那为什么我不直接选择这个方案,还要继续分析呢?

答案也很简单,我认为这个方案,虽然灵活,但是灵活却给它带来了使用上的繁琐,每个接口每次调用都必须传入全路径作为参数,不仅繁琐而且接口一多还不好管理

那 民间大牛解决方案 可行? 但是我在前面已经说了这个不可行啊?

这个方案虽然可以支持运行时动态切换 BaseUrl 但是它是全局处理,一经使用改变的是所有请求的 Url ,所以它并不支持多 BaseUrl

并且更可怕的是,这个方案不仅不支持多 BaseUrl ,还会影响 官方静态解决方案 和 官方动态解决方案 这两个支持多 BaseUrl 的方案,因为不管你注解里面声明的是什么全路径,它的 Interceptor 拦截器,都会强行将这个请求的 Url 改成它的 BaseUrl ,所以这个方案注定只适合只有一个 BaseUrl 但需要动态改变的项目

那岂不是 4 个解决方案都不可行?说这么久说个毛线啊?

方案全部淘汰?散会?

等等别急啊,虽然我站在我的角度, Pass 了文中提到的所有已存在的解决方案

但是大家仔细想想,如果网上已经存在完美的解决方案,那我还写这篇文章有什么意义?必定是没有我满意的解决方案,我才会自己动手去解决并分享啊,毕竟我是一个不愿意写重复内容的有为青年,只要是我写的内容肯定是会让大家学到不一样的知识三 ✊,不然不是砸自己招牌

好了,不逗大家了,开整!

别急,还有大招!

虽然在已有的解决方案当中没有找到让我满意的,但是在遇到问题时,冷静分析现有解决方案是很有必要的,理解前人的思路后才会对整个问题理解得更透彻,我的很多文章也都是以分析和解决思路为主,授人以鱼不如授人以渔,所以我不会直接告诉你答案,先分析一波,理清思路

这不,在分析 民间大牛解决方案 时,虽然最后发现这不是自己想要的解决方案,但是作为有发散思维的我,又是灵机一动,借助原有解决方案在上面这样一改不是就可行了?

如何改善原有方案?

上面的分析已经说了 民间大牛解决方案 ,可以在 Interceptor 拦截器中设置一个全局的 Host(Host 可以理解为 BaseUrl) ,拦截器会强行将这个 Host 应用到所有的请求上,改变该请求原有的 Url,这样导致了只会同时存在一个 Host

所以我在想,将这个唯一的 Host 变量改为集合,以存储多个 Host ,在将不同的 Host 应用到不同的请求上,不就可以支持多 BaseUrl?

实践想法

说干就干,于是我自己建了一个全局的容器来存储多个 Host,这样我就可以在 App 运行时的任何时间,任何地点随意新增,修改,删除 Host

遇到问题

但是问题来了,我想要将不同的 Host 应用到不同的请求上,但我怎么知道什么请求需要什么样的 Host ,每个请求总要有个标记,让我知道他需要什么样的 Host 吧

于是我就在想 Retrofit 有什么方法,可以在请求之前给每个请求加上不同的字符串标记,于是我很自然的想到了 Header ,Retrofit 正好有 @Headers 这个注解,可以给每个接口方法上加入自定义 Header

再次解决难点

我给需要不同 BaseUrl 的接口方法上加入了自定义的 Header ,以标明每个接口需要的 Host 的 Name ,而这个 Name 对应的值就是 Host,但这个值不是在 @Headers 中被指定的,它是可以动态改变的

存储 Host 的容器是一个 Map, key 就是这个 Name ,value 才是 Host ,拦截器每次拦截到请求时,会判断这个请求是否有这个自定义 Header,
有的话,拿到这个 Header 中标注的 Name,然后用这个 Name ,去那个存储 Host 的全局 Map 中 get(name),拿到对应的 Host 再应用到请求上不是就达到支持多个 BaseUrl 了?

如果想动态改变某个 Host 也简单,将新的 Host 以同样的 Name put(name) 进这个全局 Map ,到时候拦截器,使用这个 Name get(name) 出来的值,就已经是改变后最新的 Host ,在将这个 Host 应用到请求上不是就达到动态改变 BaseUrl 了?

这不,两个需求同时满足!

优化方案

这个方案就两步,给需要不同 BaseUrl 的请求设置 Header (想用 Retrofit 默认 BaseUrl 的接口,或者使用 官方静态解决方案, 官方动态解决方案 就不需要设置),在通过全局容器来管理 BaseUrl

针对于那种只有一个 BaseUrl 但需要动态改变的项目,本框架提供了一个 GlobalDomain 来优化这个场景,不需要给接口加 Header ,只需要一步,向全局容器 put(GlobalDomain) 你想要改变的 BaseUrl 就可以了

比 官方动态解决方案 给每个接口传全路径作为参数,要简单的多, 官方动态解决方案 注定只适合那种只有一两个需要动态改变 BaseUrl 的接口

总结

以上提到的解决方案,已经优化并封装成了三方库并上传至 Jcenter,方便大家使用

本解决方案主要适合,需要同时具备多 BaseUrl 以及动态改变 BaseUrl 的项目,或者只有一个 BaseUrl ,但需要动态改变 BaseUrl 的项目

如果对于只需要多 BaseUrl 不需要动态改变 BaseUrl 的项目,其实用 官方静态解决方案 就已经足够了,但我还是推荐用我的这个解决方案,因为需求都是会变的,如果一旦要加入动态改变 BaseUrl 的需求,如需要动态切换 生产环境 和 开发环境 ,那这时怎么办,一个个改掉每个接口注解里面的全路径?

Github : 具体使用看 Demo ,记得 Star !


Hello 我叫Jessyan,如果您喜欢我的文章,可以在以下平台关注我

– The end

Retrofit 动态修改BaseUrl 最近项目有关需求,需要app在调用不同模块时,发起不同url的请求。经过查找资料发现可以通过retrofit的拦截器解决。 1.在网络请求接口中添加@Headers 在网络请求接口中添加@Headers({“url_name:xxx”})。 public interface RetrofitService { String URL_WEATHER = "url_name:weather... 阅读详情

相关推荐

Retrofit源码分析&实践(六)【Retrofit 多BaseUrl问题解决】

本节到这里就基本结束了,我们回顾一下。解决retrofit 多baseUrl的动态解决方案就是RetrofitManager作为单例类,使用map保存baseurl-retrofit的一一对应保存为了解决需要记忆baseurl-retrofit一一对应关系的问题,我们引入自定义注解BaseUrl,给需要的接口类,直接添加这个注解。

itbird的专栏 6357

Retrofit动态设置BaseUrl

Retrofit动态设置baseUrl有四种方式 需要使用带host的全路径,否则不会更改,只会和原拼接 正确使用示例 三. @url不改变baseUrl时的用法 像上面第二点说的,当不使用scheme+host全路径的用法时,我们在请求一些很长的url并且参数是固定的接口时,使用@url会很方便。 特别需要注意的是:当我们在结点url上添加一个前置 / 符号时,每个加到host Url后面的东西都会被省略掉。建议在使用@url时,不要在结点url添加前置 / 符号 。

闪亮的大早的博客 3577

【MIT-BEVFusion代码解读】第四篇:融合特征fuser和解码特征decoder

的大小,实际上源代码也是这么做的。最后将得到两个分支的特征进行。,第一个特征使用卷积降低通道数即可,第二个则需要反卷积来提升。所以backbone只有两个分支,都是5个卷积模块组成。的长和宽都减半至90,然后在经过5个相同的。将通道降至128,后面再接5个相同的。,将通道数128上至256,并且将。特征进行融合,这里使用的。部分由两部分组成,分别是。,这个分支首先经过第一个。,然后再卷积得到 =>提取特征,最后得到特征。得到了两个大小不同的。

非晚非晚的博客 2957

Retrofit 动态管理和修改 BaseUrl,从未如此简单

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。

2401_84149496的博客 1270

Ubuntu22.04下ROS2与PX4仿真环境搭建全流程解析

本文详细解析了在Ubuntu22.04系统下搭建ROS2与PX4仿真环境的全流程,包括系统准备、ROS2 Humble安装、PX4飞控环境部署、ROS2与PX4通信桥梁搭建等关键步骤。针对常见问题提供了解决方案,并分享了性能优化和开发调试技巧,帮助开发者快速构建无人机仿真开发环境。

weixin_29248653的博客 607

通过 CoovaChilli 和 FreeRADIUS 搭建一个公共 Wi-Fi 的认证系统,实现用户连接到 Wi-Fi 后通过 Captive Portal(强制登录页面)进行认证

要实现固定设备连接的功能,你可以通过MAC 地址认证来限制哪些设备可以通过 FreeRADIUS 进行身份验证和连接。你可以在 FreeRADIUS 的users文件中直接配置允许的设备的 MAC 地址,也可以通过数据库存储和查询设备信息,进一步提高管理效率。通过这些方法,你可以灵活地控制哪些设备能够访问你的 Wi-Fi 网络。

m0_69943017的博客 2647

Retrofit动态设置baseUrl和@url的使用

一. Retrofit动态设置baseUrl有四种方式: 配置多个retrofit对象:即不同的 BaseUrl 使用不同的 Retrofit 对象来创建 ApiService 进行请求,这样只要新增一个不同的 BaseUrl ,那就需要重新创建一个新的 Retrofit 对象。 缺点:代码冗余,浪费资源,ApiService太多,不好管理。 @Get , @Post 全路径:这些标注到每个接口方法上的注解不仅可以传相对路径,还可以传全路径,这样我们就可以做到不同的接口使用不同的 BaseUrl ,使用全

liuxiaopang520的博客 1万+

Excel炒股党必备:手把手教你用Power Query免费获取并刷新股票历史数据

本文详细介绍了如何利用Excel中的Power Query工具免费获取并自动刷新股票历史数据,特别适合Excel炒股党。从环境配置、数据源选择到实战操作,手把手教你建立智能数据管道,实现高效投资分析。通过参数化股票代码和定时刷新功能,大幅提升数据更新效率。

weixin_26767391的博客 654

解决Retrofit多BaseUrl及运行时动态改变BaseUrl?

原文地址: http://www.jianshu.com/p/2919bdb8d09a 解决Retrofit多BaseUrl及运行时动态改变BaseUrl(一) 解决Retrofit多BaseUrl及运行时动态改变BaseUrl(二) 前言 Hello,我是 JessYan,作为一个喜欢探索新颖解决方案的我,在 上篇文章 中,向大家介绍了怎样通过一行代...

weixin_34013044的博客 498

微信小程序实现锚点效果 scroll-view的scroll-into-view属性

小程序中实现锚点效果,可以直接使用scroll-view的scroll-into-view属性就可以实现锚点效果,比较方便简单。那么需要用到scroll-view那些参数呢,下面具体讲讲:效果展示: wxml **注意:**viewid值是动态的,通过setData设置即可。js wxss......

FaxMiao的博客 5449

YOLOv5改进 | 注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制,附二次创新)

本文给家大家带来的改进机制是iRMB,其是在论文Rethinking Mobile Block for Efficient Attention-based Models种提出,论文提出了一个新的主干网络EMO(后面我也会教大家如何使用该主干,本文先教大家使用该文中提出的注意力机制)。其主要思想是将轻量级的CNN架构与基于注意力的模型结构相结合(有点类似ACmix)我将iRMB和C2f结合,然后也将其用在了检测头种进行尝试三种结果进行对比,针对的作用也不相同,但是无论那种实验均有一定涨点效果。

Snu77的博客 2570

解决Retrofit多BaseUrl及运行时动态改变BaseUrl(二)

在name=jess"中,其中的"/wiki"和"/part"就是PathSize就是的个数这个URL地址的PathSize就是 2, 第一个是"/wiki",第二个是"/part",可以粗略的理解为域名后面跟了几个"/"PathSize就是几其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。

2401_84149635的博客 1207

金三银四!风控建模岗面试题库大全:从理论到实战避坑指南

风控建模面试大全

阿黎逸阳的博客 767

android 动态切换url,RetrofitUrlManager 解决Retrofit多BaseUrl及运行时动态改变BaseUrl

RetrofitUrlManagerLet Retrofit support multiple baseUrl and can be change the baseUrl at runtime.OverviewIntroduction以最简洁的 Api 让 Retrofit 同时支持多个 BaseUrl 以及动态改变 BaseUrl.NoticeDownloadimplementation 'me...

weixin_42341237的博客 2258

13、控制依赖与切片的新基础及递归While程序的摘要

本文探讨了控制依赖和程序切片的新研究进展,并提出了一种用于递归While程序的广义过程摘要概念和验证框架。文章介绍了控制依赖的新定义及其优势,程序切片的相关工作,以及递归While程序的过程摘要在完全正确性和终止性证明中的应用。通过阶乘和插入排序程序的示例分析,展示了过程摘要的有效性。未来的研究将聚焦于并发程序的依赖计算、依赖关系的语义连接以及时间属性的保留。

kotlin6android的博客 86

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

使用Retrofit请求时需要多个baseurl动态切换

项目中使用Retrofit进行请求时,后台接口的域名有多个,现记录一下,以备后面使用: api接口中有两个baseurl: public static String baseUrl = "https://192.168.1.1/"; public static String sfbaseUrl = "http://192.168.1.2/"; 第一步、在service代码中添加@Head...

冬日-雪的博客 5100

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Retrofit多BaseUrl终极指南:快速实现动态URL切换

RetrofitUrlManager是一个专为Retrofit设计的轻量级框架,它以最简洁的API让Retrofit同时支持多个BaseUrl以及在运行时动态改变BaseUrl,完美解决了移动应用开发中多环境切换、服务端API地址变更等常见需求。 ## 📌 为什么需要动态BaseUrl切换? 在实际项目开发中,我们经常会遇到以下场景: - 应用需要连接不同环境(开发/测试/生产)的API服务

gitblog_00987的博客 661

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Retrofit动态切换baseUrl

说明:对于一些功能,需要多个BaseURl来请求不同服务器地址的api,我不可能有几个BaseURl,我就实例化几个Retrofit实例。这样做很不科学,要是BaseURl有上百个那个工作量是没法去估计的。为了解决这个问题方法如下: 运用应用拦截器Interceptor,来获取到app到okhttp中间层的request,对它进行修改、处理。 步骤如下: 这是两个api的BaseUrl publi...

weixin_33979745的博客 399

Android中retrofit切换baseUrl

一般来说,一个APP中的域名应该固定只有一个。我们在网络请求时可以很方便的写上我们的域名来替代ip+端口号从而进行网络请求。但是有时候我们的应用需要,动态的设置我们的域名的时,写上固定的域名就无法使用了。关键是,在我们使用retrofit时,这种情况就更加的棘手。因为retrofit是默认不支持切换baseurl的。那么此时,我们可以通过本文的方法来进行baseurl的切换。 主要的思路是,在网络...

千弘 4396
上一篇: 一行代码实现Okhttp,Retrofit,Glide下载上传进度监听
下一篇: MVPArms MVP+Dagger+Rxjava+Retrofit快速集成框架
JessYanCoding
博客等级 码龄10年 63粉丝 15原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值