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

Android · jessyan · 于 发布 · 最后由 8855220回复 · 712 次阅读
2856 1522461025

原文地址: https://www.jianshu.com/p/35a8959c2f86

前言

我在之前的文章 《解决Retrofit多BaseUrl及运行时动态改变BaseUrl》 中,介绍了市面上能够解决此类问题的 4 个常见的解决方案,并开源了自己经过优化后的解决方案 RetrofitUrlManager,现在再为大家带来此系列的第二篇文章,这篇文章主要介绍 RetrofitUrlManager 针对 BaseUrl 替换逻辑的重大升级,因为这个升级对于 RetrofitUrlManager 足够重要,将使 RetrofitUrlManager 能够从容应对更多复杂的需求,所以单独写一篇文章让更多的人能够知道

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

为什么不使用多 Retrofit 实例的方案?

在上篇文章 《解决Retrofit多BaseUrl及运行时动态改变BaseUrl》 中,4 种方案的特点和不足我都描述的很清楚,建议没看过这篇文章的可以去看看这篇文章,扩宽知识面,在后面的时间里经常有人问我为什么不使用多 Retrofit 实例的方案,多个 Retrofit 实例看起来并不会占用多少资源啊?

在回答之前为了让看这篇文章的人能了解我在说什么,所以我再粘贴下 上篇文章 中关于这个方案的部分描述

民间常用解决方案:

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

我在这篇文章中重新回答下这个问题,为每个不同的 BaseUrl 都创建一个其他配置属性都一模一样的 Retrofit 实例不止会造成资源的浪费,还会造成接口管理成本的增加,这个才是最重要的一点, 举个例

我们平时项目中所有的 ApiService 都是使用同一个 Retrofit 实例的 Retrofit#create(ApiService) 方法进行实例化后开始接口的请求

但是当项目中出现多个 Retrofit 实例后,我们在开发中不光要区分哪些接口使用哪个 ApiService,还要区分哪些 ApiService 需要使用哪个 Retrofit 实例进行实例化,如果 ApiService 使用错误的 Retrofit 实例进行实例化,那这个 ApiService 的所有接口请求都注定完全失败

越复杂的项目,开发人数越多的项目,出错的风险就越大,并且扩展性也在大打折扣,后面一有变更将会十分痛苦,随着项目中接口的增加,以及 Retrofit 实例的增加 (BaseUrl 的增加),这个管理成本会成几何倍的增加

使用多 Retrofit 实例的方案前期投入成本过高,可能会影响之前项目管理接口的方式,某些封装过 Retrofit 的项目,也可能需要大改,对于老项目的接入不利,而使用 RetrofitUrlManager 不仅可以满足多 BaseUrl 及运行时动态改变 BaseUrl 的需求,还具有热插拔以及低侵入性的特点,在使用过程中将不会影响到之前的接口管理方式和使用方式,还具有极强的扩展性,可应对后面陆续增加的极其复杂的 BaseUrl 替换需求

升级之前的 RetrofitUrlManager 的问题

此次升级之前的 RetrofitUrlManager 版本,只是将 上篇文章 的思想完全实现,有了整个框架的基础,但是在动态替换 BaseUrl 方面还不够强大,最被大家吐槽的就是只能替换 BaseUrl 的域名

比如一个需要替换 BaseUrlUrl 地址为 "https:www.google.com/api/v2",其中 "https:www.google.com/api" 是我们传给 RetrofitBaseUrl,这时我们使用 RetrofitUrlManager 框架,想把 BaseUrl 替换成 "https:www.github.com",我们期望的替换后的 URL 地址是 "https:www.github.com/v2",但使用框架替换后的实际 URL 地址是 "https:www.github.com/api/v2", "/api" 作为 BaseUrl 的一部分并没有被新的 BaseUrl 替换掉,只是替换了 BaseUrl 中的域名

RetrofitUrlManager 是如何改善的

改善之前先要先分析为什么会这样?因为 RetrofitUrlManager 框架在拦截器中拦截到的 URL 地址是 Retrofit 已经把 BaseUrl 和接口注解中的相对路径合并后得到的最终路径地址,所以框架并不知道您传给 RetrofitBaseUrl 除了域名外还包含后面的 "/api",框架不知道 BaseUrl 的具体值,所以框架只会默认所有的 BaseUrl 都只含有域名,所以也就只能替换域名

高级模式

想要解决此类问题也很简单,告诉 RetrofitUrlManager 框架您传给 RetrofitBaseUrl 具体值即可,所以框架升级后增加了 RetrofitUrlManager#startAdvancedModel(String) 方法,在 App 初始化时将您传给 RetrofitBaseUrl 同样传给此方法,即可开启高级模式,高级模式即可替换拥有多个 pathSegmentsBaseUrl,不再局限于只能替换域名

什么是 pathSegment?

"https://www.github.com/wiki/part?name=jess" 中,其中的 "/wiki""/part" 就是 pathSegment, PathSize 就是 pathSegment 的个数

这个 URL 地址的 PathSize 就是 2, 第一个 pathSegment"/wiki",第二个 pathSegment"/part",可以粗略的理解为域名后面跟了几个 "/" PathSize 就是几

高级模式的替换规则

  1. URL 地址为 "https://www.github.com/wiki/part",您在 App 初始化时传入 RetrofitUrlManager#startAdvancedModel(String)BaseUrl"https://www.github.com/wiki",您想替换成的 BaseUrl 地址是 "https://www.google.com/api",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/api/part"

  2. URL 地址为 "https://www.github.com/wiki/part",您在 App 初始化时传入 RetrofitUrlManager#startAdvancedModel(String)BaseUrl"https://www.github.com/wiki",您想替换成的 BaseUrl 地址是 "https://www.google.com",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/part"

  3. URL 地址为 "https://www.github.com/wiki/part", 您在 App 初始化时传入 RetrofitUrlManager#startAdvancedModel(String)BaseUrl"https://www.github.com",您想替换成的 BaseUrl 地址是 "https://www.google.com/api",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/api/wiki/part"

超级模式

超级模式是高级模式的加强版,优先级高于高级模式,按理说高级模式就能满足开发中的大部分需求,那什么又是超级模式呢?那就要先来说说高级模式了

高级模式的原理

在高级模式中您需要在 App 初始化时将您传给 RetrofitBaseUrl 同样传给 RetrofitUrlManager#startAdvancedModel(String) 一份,用以开启高级模式,成功开启高级模式后,这个传给 RetrofitUrlManager#startAdvancedModel(String)BaseUrl 就会作为框架替换 BaseUrl 的基准

什么叫作基准呢? 用此 BaseUrl 开启高级模式,并不意味着框架就只能替换 域名"www.github.com" 前两个 pathSegments"/wiki/part"URL,只要拥有域名以及大于或等于两个 pathSegmentsURL 都可以被框架替换,因此高级模式只会保存传入 RetrofitUrlManager#startAdvancedModel(String)BaseUrl 的格式 (保存 pathSegments 的个数),并不是保存具体的值

高级模式的局限

如果传给 RetrofitUrlManager#startAdvancedModel(String)BaseUrl"https://www.github.com/wiki/part" (PathSize = 2),框架就会将项目中所有 URL 中的 域名 以及 域名 后面的前两个 pathSegments 作为可被替换的 BaseUrl 整体,意味着框架只会将 URL 中的 域名 以及前两个 pathSegments 剪切并替换为您期望的 BaseUrl

这时服务器突然作出调整,项目中的一部分 URL 只需要将 "https://www.github.com/wiki" (PathSize = 1) 替换掉, 第二个 pathSegment "/part" 不再作为 BaseUrl 的一部分,不能被替换掉,必须要保留下来

这时项目中就出现了多个需要被替换的 BaseUrl 格式 (PathSize 不同),有些 URL 只需要替换 域名 以及前两个 pathSegments,有些又只需要替换 域名 以及前一个 pathSegments,但是在开启高级模式时,只保存了一个 BaseUrl 的格式,这时使用高级模式实现此需求就比较棘手

这个需求是一个比较变态的需求,可能很多人遇不上,但是我想让您知道当您遇上了也不要怕,因为 RetrofitUrlManager 的超级模式已经帮您考虑周全

超级模式的用法

超级模式与高级模式不同的是,开启超级模式并不需要调用 API,只须要在需要开启超级模式的 Url 尾部加上 RetrofitUrlManager#IDENTIFICATION_PATH_SIZE (#baseurl_path_size=) + PathSize,这样就明确的告诉了框架,在这个 URL 中需要被替换的 BaseUrl 含有几个 pathSegments,相当于每个 URL 都可以指定自己需要被替换的 BaseUrl 的格式,这样就比高级模式只能在 App 初始化时,指定一个全局的 BaseUrl 格式灵活得多,如果当您开启高级模式的同时也开启了超级模式,由于超级模式的优先级高于高级模式,所以只会执行超级模式

超级模式的替换规则

  1. URL 地址为 "https://www.github.com/wiki/part#baseurl_path_size=1""#baseurl_path_size=1" 表示其中 BaseUrl"https://www.github.com/wiki",您想替换成的 BaseUrl 地址是 "https://www.google.com/api",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/api/part"

  2. URL 地址为 "https://www.github.com/wiki/part#baseurl_path_size=1""#baseurl_path_size=1" 表示其中 BaseUrl"https://www.github.com/wiki",您想替换成的 BaseUrl 地址是 "https://www.google.com",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/part"

  3. URL 地址为 "https://www.github.com/wiki/part#baseurl_path_size=0""#baseurl_path_size=0" 表示其中 BaseUrl"https://www.github.com",您想替换成的 BaseUrl 地址是 "https://www.google.com/api",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/api/wiki/part"

  4. URL 地址为 "https://www.github.com/wiki/part/issues/1#baseurl_path_size=3""#baseurl_path_size=3" 表示其中 BaseUrl"https://www.github.com/wiki/part/issues",您想替换成的 BaseUrl 地址是 "https://www.google.com/api",经过框架替换后生成的最终 URL 地址为 "http://www.google.com/api/1"

三种模式比较

在升级之前,框架就只有一个默认的普通模式 (只能替换域名),在升级之后新增了 高级模式超级模式,这两个模式让框架变得更加强大,在上面的内容中也详细的介绍了这两个模式,现在就来总结下这三个模式,让大家能够按照自己的需求选择出最适合的模式

替换 BaseUrl 的自由程度 (可扩展性)

普通模式 < 高级模式 < 超级模式

  • 普通模式: 只能替换域名

  • 高级模式: 只能替换在 RetrofitUrlManager#startAdvancedModel(String) 中传入的固定 BaseUrl 格式

  • 超级模式: 每个 URL 都可以随意指定可被替换的 BaseUrl 格式

使用上的复杂程度

普通模式 < 高级模式 < 超级模式

  • 普通模式: 无需做过多配置

  • 高级模式: 在 App 初始化时调用一次 RetrofitUrlManager#startAdvancedModel(String) 即可

  • 超级模式: 每个需要开启超级模式的 URL 尾部都需要加入 RetrofitUrlManager#IDENTIFICATION_PATH_SIZE (#baseurl_path_size=) + PathSize

总结

由此可见,自由度越强,使用上也越复杂,所以可以根据自己的需求选择对应的模式,并且也可以根据需求的变化随意升级或降级这三种模式

这次更新让 RetrofitUrlManager 的能力提升了一个档次,足以应对各种复杂的 BaseUrl 替换需求,正因为 RetrofitUrlManager 极强的扩展性,现在甚至可以做到,让服务器可以通过远程动态控制项目中的多个 BaseUrl

如果还有什么问题或者需求可以给我提 Issues,如果 RetrofitUrlManager 能够给您带来实质的帮助,也请不要吝啬您的 Star


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

-- The end

共收到 3 条回复
96
8855220 · #1 ·

茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能

96
8855220 · #2 ·

茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能
茉莉外約line:8855220 找大奶妹 奶水人妻18歲嫩妹第一次下海 服務主動配合度高 欲拒還迎讓你欲罷不能

96
8855220 · #3 ·

台灣全省貼心外約line:8855220
最貼心的服務 最平價的消費 給您六星級的享受
☆茉莉外送茶LINE:8855220
每個男人心中都有一個夢中情人
把你的夢中情人告訴茉莉
性福從這裡開始 給你最貼心的愛(加我請密我哦)LINE:8855220

茉莉惠民套餐:
1:新客戶約妹可優惠1000
2:每日前三位和我預約妹妹的可優惠2000+贈送半價優惠券1張
3:一次性買兩節優惠2000 一次性買三節免費送一節或優惠3000
4:生日當月約妹祝壽約一節免費送一節
5:介紹或者攜1-2友人消費免1500
攜兩位友人消費免2000 3-5位免3000送三張半價優惠券
6:北部消費一節7000買兩節可免費送一節哦
中部南部消費一節5000買兩節可免費送一節哦

這裡有
活潑可愛的學生妹 楚楚動人的老師
性感迷人的櫃姐 清純嬌小的護士
淫蕩敢玩的人妻 火辣妖嬈的O
騷氣十足的酒促妹 魔鬼身材的麻豆、空姐的神秘小穴等你探索
把你喜歡的類型告訴我 讓她們
陪你一起神遊仙境 欲仙欲死(✿◡‿◡)
快點加茉莉的賴:8855220 快點加茉莉的賴:8855220
快點加茉莉的賴:8855220 快點加茉莉的賴:8855220

★【優質找茶】全台灣最大找茶 妹妹多、條件好、素質優、多年經營、安全可靠
★【服務地區】台北/新北/台中/彰化/高雄 /台南/林口/龜山/彰化/南投/草屯
★【服務內容】洗澡 愛愛 口交 事後澡 按摩 淋浴 喇舌 69 口爆 乳交 顏射 舔鮑 螞蟻上樹等等…
★【營業時間】上午12:00~淩晨4:00,天天有新茶,眾多美女任君挑選。
★【外送福利】依照您所想要的條件安排、見面滿意消費、可選可換、不催趕效率第一
★【杜絕詐騙】一律見妹妹本人現金消費,不強迫、免匯款、免點數、免轉帳
★【 VIP客戶】熟客可享最真的VIP服務,新妹早知道,早吃香,早優惠,“3早”服務,-值得您期待。
★【 外送地點】:各大飯店HT 汽車旅館MT 熟客可住家和3P?一次三節免費送一節
性福從這裡開始 給你最貼心的愛(加我請密我哦)LINE:8855220

所有的合作都是講究誠信和真心的 你真心要約 茉莉便給你最真誠的介紹+賴:8855220
如果你以前有過配合的茶莊 不管那個茶莊讓你感覺如何
請您不要以偏概全 每個茶莊都不一樣 每個介紹人性格不一樣
所以給你的介紹的妹妹 和彼此雙方的感覺都是不一樣的
茉莉做這個工作從來都不是只做一次性生意的 都是以長期合作為目的
所以每一次介紹 都是用最認真的態度 給你最好的妹 絕不敷衍
你約多少價位就給你多少價位的 不會以爛充好
因為你約的價位茉莉抽多少都是固定好的
不會因為給你差的我就多抽 給你好的我就少抽 不是這樣的
所以哥哥們可以放心讓茉莉幫你介紹
保證給你前所未有的體驗和快感

外送茶坊/臺北/
新竹叫小姐/臺中兼職妹妹外送/竹 北好茶外送/高雄鐘點情人/中山區一夜情

絕色正妹外送/大同區約妹/賴:8855220
松山區找茶喝/大安區找 女人/南港區叫妹/萬華區約妹打炮/信譽區美女外送/士林

區酒店外送一夜情/北投旅館約妹愛愛
/內湖 區喝茶找女人/文山區找茶外送/土城找茶妹/汐止正妹外送/中和探索約妹愛

愛/泰山兼職美女外 送/永和住家叫小姐/
新莊motel外送/板橋學生妹兼職外送/新店性感美女外送/蘆洲區愛愛茶/三重性感

茶/淡水風騷茶/林口技術茶/龜山嬌小茶/
中區正妹兼職/北區找炮妹/東區叫雞/西區全套外送服務/南區淫蕩茶/西屯區美艷

茶/南屯區白皙茶/北屯區熟女茶/大理人妻茶/賴:8855220
大雅看照約妹/豐原約妹打炮/沙鹿兼職美女/彰化美腿茶/南投口碑茶/員林氣

質茶/前金區喝茶/苓雅區外送茶/鼓山區看照約
妹/前鎮區美腿茶/三民區火辣茶/新興區惹火嫵媚茶/左營區MT外送/小港青澀茶/鳳

山領薪必喝茶/汽車旅館約妹/火車站叫茶/
伊莉喝茶吃魚論壇/玩美情人魚 訊論壇/成人夜遊魚訊茶訊交流討論區/男人的性福

天堂/完美戀人魚茶漁會論壇,BJ論壇網/
小女人俱樂部/141香港論壇/ 歡樂茶訊魚訊/ YouTube/FT茶魚論壇/八大娛樂網/台

情綜合論壇台灣情色網/伊魚網/美人魚外送/
援交妹網站/男人幫論壇香港論壇/美女外送/傳播妹/情色AV/台中應召站/成人性愛

//喝茶論壇/援交/兼職美媚/正妹辣妹包
你爽//台中叫小姐/色情/台中買茶/茶莊外送/鐘點情人/情色自拍/無碼/全套外送/

台灣正妹/辣妹兼職/台中好茶/台中外送茶/LINE:8855220
援助交際留言板/UT聊天室/包養/男女愛愛/辣妹宅配/好茶外送/台北清涼茶莊/更

多優質妹妹/台北外送茶莊/高雄外送茶/新竹
外送茶/洗澡/愛愛//夜總會俱樂部/激情A片網站/喝茶討論區/大雅外送茶/烏

日外送旅館飯店/新店全套外送茶/南屯外送茶/賴:8855220
西屯叫小姐/北屯一夜情/中區東區外送茶莊/東海鐘點情人/大理板橋金色年代

一夜情侶/中山外送茶/文山絕色正妹/松山援
交全套妹妹/大同大安找女人五股喝茶服務外送一夜情鐘點情/台北市外送茶/士林

區內湖外送茶夜店嗨妹激情四射/北投外送茶/
信義區外送茶/南港外送茶/萬華區外送茶/三重外送茶/土城外送茶/永和外送茶/汐

止外送茶/新莊外送茶/樹林外送茶/板橋外送賴:8855220
茶/瀘州外送茶/新興區外送茶/前金區外送茶/苓雅區外送茶/鼓山區外/外

送茶/外送服務/學生妹兼職愛愛/旅館叫小姐/
住家叫小姐/找茶討論區/台北出差叫小姐 /賴:8855220

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册