Retrofit 的 Scala Adapter:用 Scala Future 类型化 HTTP 客户端
Retrofit 的 Scala Adapter用 Scala Future 类型化 HTTP 客户端【免费下载链接】retrofitA type-safe HTTP client for Android and the JVM项目地址: https://gitcode.com/gh_mirrors/re/retrofit导读本文讲解 Retrofit 官方适配器adapter-scala的完整用法与底层原理。通过注册ScalaCallAdapterFactory你可以让 Retrofit 服务接口直接返回scala.concurrent.Future把异步 HTTP 请求无缝接入 Scala 的Future/Promise生态。读完本文你将掌握该适配器的两种返回类型配置FutureT与FutureResponseT、Maven/Gradle 依赖引入方式、错误语义差异以及它内部的CallAdapter适配机制与测试验证方式。一、什么是 Scala Adapterretrofit-adapters/scala模块是一个标准的 RetrofitCallAdapter适配器其唯一职责是把 Retrofit 的CallT转换为 Scala 的Future。模块的 POM 描述见 retrofit-adapters/scala/gradle.properties将其定位为 A Retrofit CallAdapter for Scalas Future。在默认情况下Retrofit 服务接口方法只能返回CallT或内置支持的其它类型。而ScalaCallAdapterFactory允许你写出这样的接口interface MyService { GET(/user) FutureUser getUser(); }请求发出后立即返回一个Future无需手动维护Callback也无需依赖 RxJava 等其它异步库。适用前提该模块基于scala.concurrent.Future与scala.concurrent.Promise实现需要项目引入 Scala 标准库scala-library。从源码结构看它适用于同时使用 Retrofit 与 Scala 的 JVM 项目如 Scala/JVM 服务端或混合语言工程。二、快速上手注册 CallAdapter 工厂在构建Retrofit实例时通过addCallAdapterFactory注册ScalaCallAdapterFactory即可对应 retrofit-adapters/scala/README.md 中的用法Retrofit retrofit new Retrofit.Builder() .baseUrl(https://example.com/) .addCallAdapterFactory(ScalaCallAdapterFactory.create()) .build();工厂采用无状态单例工厂设计create()是唯一的公开入口构造函数为私有见 ScalaCallAdapterFactory.javapublic static ScalaCallAdapterFactory create() { return new ScalaCallAdapterFactory(); } private ScalaCallAdapterFactory() {}随后服务接口的返回类型就可以使用Futureinterface MyService { GET(/user) FutureUser getUser(); }注册时有两个注意点CallAdapter 工厂可以叠加注册。如果项目中同时使用多个适配器如 Scala 与 Java 8CompletableFutureRetrofit 会按注册顺序依次询问各工厂是否能处理当前返回类型无法处理的工厂返回null交给下一个。Converter 工厂仍按需注册。ScalaCallAdapterFactory只负责把CallT变成Future响应体到User的反序列化仍然由Converter.Factory如 Gson、Moshi完成二者职责正交。三、两种返回类型配置ScalaCallAdapterFactory支持Future泛型参数的两种形态源码 Javadoc 与get方法明确说明见 ScalaCallAdapterFactory.java1. 直接返回响应体FutureTGET(/user) FutureUser getUser();语义如下对应 BodyCallAdapter.java 的实现场景行为2XX 成功响应Future成功完成值为反序列化后的响应体response.body()非 2XX 响应Future以retrofit2.HttpException失败携带 HTTP 状态码与错误信息网络错误Future以java.io.IOException失败核心实现使用Promise桥接 Retrofit 的异步回调Override public FutureT adapt(CallT call) { PromiseT promise Promise.apply(); call.enqueue(new CallbackT() { Override public void onResponse(CallT call, ResponseT response) { if (response.isSuccessful()) { promise.success(response.body()); } else { promise.failure(new HttpException(response)); } } Override public void onFailure(CallT call, Throwable t) { promise.failure(t); } }); return promise.future(); }2. 返回 Response 包装FutureResponseTGET(/user) FutureResponseUser getUserResponse();语义如下对应 ResponseCallAdapter.java 的实现场景行为任意 HTTP 响应含 4XX/5XXFuture成功完成值为完整的ResponseT对象通过response.isSuccessful()判断业务是否成功可读取errorBody()网络错误Future以java.io.IOException失败Override public FutureResponseT adapt(CallT call) { PromiseResponseT promise Promise.apply(); call.enqueue(new CallbackT() { Override public void onResponse(CallT call, ResponseT response) { promise.success(response); // 不区分状态码全部成功返回 } Override public void onFailure(CallT call, Throwable t) { promise.failure(t); } }); return promise.future(); }两者如何选择需要区分业务成功/失败直接看Future成功与否时选FutureT需要拿到状态码、响应头或错误响应体时选FutureResponseT。注意FutureResponseT形态下Future几乎总是成功完成HTTP 错误不会抛异常需要自己检查Response.isSuccessful()。工厂的类型判定逻辑ScalaCallAdapterFactory.get()的完整判定流程见 ScalaCallAdapterFactory.java若返回类型原始类型不是Future.class返回null不处理交给下一个工厂若是裸Future未参数化抛出IllegalStateExceptionFuture return type must be parameterized as FutureFoo or Future? extends Foo取Future的第一个泛型参数上界作为内部类型若内部类型不是Response则走BodyCallAdapter若内部类型是Response要求其必须参数化如ResponseFoo或Response? extends Foo否则抛出IllegalStateException取出Response的泛型参数作为真正的响应体类型构造ResponseCallAdapter。整个解析过程复用了CallAdapter.Factory提供的getRawType与getParameterUpperBound工具方法见 CallAdapter.java因此通配符泛型同样被支持例如Future? extends User、FutureResponse? extends User都能正确解析出响应体类型。四、依赖引入Maven / Gradleadapter-scala的坐标如下对应 retrofit-adapters/scala/README.md 中的 Download 章节Mavendependency groupIdcom.squareup.retrofit2/groupId artifactIdadapter-scala/artifactId versionlatest.version/version /dependencyGradleimplementation com.squareup.retrofit2:adapter-scala:latest.version其中latest.version应替换为实际使用的 Retrofit 版本建议与核心retrofit模块版本保持一致。gradle.properties中确认了该模块的 Maven 坐标信息POM_ARTIFACT_IDadapter-scala、POM_NAMEAdapter: Scala。另外两点版本提示仓库通过 gradle/libs.versions.toml 统一管理各模块版本实际发布时adapter-scala与核心 retrofit 同步发版开发版快照snapshot可以从 Sonatype 的snapshots仓库获取用于尝鲜未发布的开发版本。五、原理剖析Future 是如何产生的Retrofit 的整套扩展机制建立在CallAdapter之上。CallAdapterR, T的核心契约见 CallAdapter.javaresponseType()返回适配器转换 HTTP 响应体时使用的值类型如FutureUser对应UserRetrofit 据此准备 Converteradapt(CallR call)把 Retrofit 的Call包装成目标类型T这里是Future。adapter-scala的两个内部适配器完整落实了该契约适配器responseType()adapt产物BodyCallAdapterT泛型参数 TFutureTResponseCallAdapterTResponse内的泛型参数 TFutureResponseT二者的共性实现思路是创建scala.concurrent.Promise调用call.enqueue(...)发起异步请求注册 RetrofitCallback在onResponse/onFailure回调中把结果转交给Promisesuccess/failure返回promise.future()作为方法返回值。由于请求走的是enqueue异步路径调用服务方法不会阻塞调用线程Future的完成时机取决于网络请求结束的时机后续可通过 Scala 的Future组合子map、flatMap、onComplete等或Await.result等待结果。测试如何验证仓库提供了两组针对性的测试是理解该适配器行为的最佳佐证FutureTest.java基于MockWebServer模拟真实 HTTP 交互逐一验证 6 种场景——FutureString的 200 成功Await.result拿到Hi、404 抛HttpException、断连抛IOException以及FutureResponseString的 200 / 404可读取errorBody()/ 断连三种行为ScalaCallAdapterFactoryTest.java验证工厂的类型解析——FutureString、Future? extends String、FutureListString、FutureResponseString等形态的responseType()解析结果以及裸Future、裸FutureResponse抛出对应IllegalStateException的行为。此外测试还表明使用该适配器时若同时配置一个简单的Converter.Factory如测试中的 StringConverterFactory.java把ResponseBody直接转成String即可跑通发起请求 → 反序列化 → 填充 Future的完整链路。六、常见问题与注意事项忘记参数化泛型接口方法写成裸Future或裸FutureResponse会在构建服务时抛IllegalStateException务必写成FutureUser、FutureResponseUser形式。非 2XX 是否抛异常FutureT会以HttpException失败FutureResponseT则成功返回Response必须自行判断isSuccessful()。两种语义不要混用。网络异常始终是IOException两种形态下连接失败、超时等网络层错误都会让Future以IOException或其子类失败。等待结果时注意超时测试中使用Await.result(future, Duration.create(5, SECONDS))设置等待上限生产代码同样应避免无限期阻塞等待。与其它适配器共存ScalaCallAdapterFactory只认Future返回类型其它类型会返回null交给后续工厂可放心与CompletableFuture、RxJava 等适配器一同注册。七、小结retrofit-adapters/scala是 Retrofit 官方为 Scala 生态提供的轻量异步适配器通过一个工厂类加两个内部CallAdapter用约一百行核心代码完整支撑了FutureT与FutureResponseT两种异步编程形态。它把 Retrofit 的Call回调模型桥接到 Scala 的Promise/Future模型上让 Scala 开发者可以用惯用的组合子风格处理 HTTP 请求同时完整保留 Retrofit 的类型安全接口声明与 Converter 反序列化体系。想进一步深入可以阅读 ScalaCallAdapterFactory.java 的类型判定源码或运行 FutureTest.java 观察两种形态在成功、4XX、网络异常三种场景下的真实行为。【免费下载链接】retrofitA type-safe HTTP client for Android and the JVM项目地址: https://gitcode.com/gh_mirrors/re/retrofit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

PCANet结合遮挡定位的人脸识别:原理、实现与调优

PCANet结合遮挡定位的人脸识别:原理、实现与调优

简介:《PCANet下的遮挡定位人脸识别算法》是一篇发表在《计算机科学与探索》上的学术论文,面向人脸识别与深度学习研究人员,聚焦自然环境下遮挡导致识别率下降的难题。论文提出将深度学习和特征点遮挡检测相结合的PCANet遮挡定位识别算法&…

2026/9/19 0:34:53 阅读更多 →
粒子群优化设计多层微波吸收材料:从调参到物理驱动的智能设计闭环

粒子群优化设计多层微波吸收材料:从调参到物理驱动的智能设计闭环

简介:本资源是一篇聚焦国防隐身技术与电磁兼容应用的学术论文,面向材料科学、电磁场与微波技术、优化算法研究领域的高校师生及工程技术人员,解决多层微波吸收材料“薄、宽、低”性能协同优化的设计难题。全文基于粒子群优化(PSO&…

2026/9/19 0:34:53 阅读更多 →
scikit-learn 1.2 版本技术解读:set_output 全面落地、交互约束直方图提升与 API 迁移路线图

scikit-learn 1.2 版本技术解读:set_output 全面落地、交互约束直方图提升与 API 迁移路线图

scikit-learn 1.2 版本技术解读:set_output 全面落地、交互约束直方图提升与 API 迁移路线图 【免费下载链接】scikit-learn scikit-learn: machine learning in Python 项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn 导读 本文基于当前仓库的…

2026/9/19 0:34:53 阅读更多 →

最新新闻

GetQzonehistory:一键导出QQ空间全部历史说说,Excel和网页版一次拿全

GetQzonehistory:一键导出QQ空间全部历史说说,Excel和网页版一次拿全

GetQzonehistory:一键导出QQ空间全部历史说说,Excel和网页版一次拿全 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 想找两年前发的某条说说,空间首…

2026/9/20 2:57:08 阅读更多 →
Docker实战指南:镜像容器、数据卷与MySQL Redis主从部署

Docker实战指南:镜像容器、数据卷与MySQL Redis主从部署

说句实在话,Docker这个东西,没接触之前你觉得它是个很玄乎的玩意儿,什么容器、镜像、编排,名词一串一串的,接触到用起来之后你会发现,它本质上就是一套“把应用连同运行环境一起打包、一键分发启动”的方案…

2026/9/20 2:57:08 阅读更多 →
ESP32-P4 USB读卡器开发实战:TinyUSB MSC与SD卡对接

ESP32-P4 USB读卡器开发实战:TinyUSB MSC与SD卡对接

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 2:57:08 阅读更多 →
TiXL 高级反馈效果 AdvancedFeedback 全解析:基于位移、模糊与边缘检测的实时图像反馈合成器

TiXL 高级反馈效果 AdvancedFeedback 全解析:基于位移、模糊与边缘检测的实时图像反馈合成器

音视频图形学桌面应用 【免费下载链接】t3 TiXL is an open source software to create realtime motion graphics. 项目地址: https://gitcode.com/GitHub_Trending/t3/t3 点击查看 免费下载 AdvancedFeedback 是 TiXL 算子库 Lib.image.fx.feedback 中的核心反馈…

2026/9/20 2:57:08 阅读更多 →
OpenResearch orx-git 技能实战:用 Git worktree 与 orx/<slug> 分支管理实验代码的版本与不可变历史

OpenResearch orx-git 技能实战:用 Git worktree 与 orx/<slug> 分支管理实验代码的版本与不可变历史

人工智能AI Agent深度研究自主智能体Agent 编排 【免费下载链接】OpenResearch Turn your coding agents into research agents 项目地址: https://gitcode.com/GitHub_Trending/op/OpenResearch 点击查看 免费下载 OpenResearch(orx)把 Git…

2026/9/20 2:57:08 阅读更多 →
切线判定到射影定理:16题几何证明链与批量核验

切线判定到射影定理:16题几何证明链与批量核验

简介:《相似三角形和圆综合题》教师版练习文档面向初中高年级及中考数学备考学生与教师,集中训练圆与相似三角形的综合证明与计算。文档收录16道典型几何题,覆盖切线判定、直径与弦的关系、圆周角与弦切角、角平分线与垂线、比例线段、勾股定…

2026/9/20 2:56:08 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →