EitherNet

EitherNet

多平台网络API响应处理框架

EitherNet是一个多平台网络API响应处理框架,主要用于Retrofit但可扩展到其他平台。它使用Kotlin密封类型提供类型安全的单一返回点,简化了错误处理流程。该框架支持自定义错误类型、结果处理、重试机制和测试功能,为开发者提供了灵活且强大的网络请求处理方案。

EitherNetAPIRetrofitKotlin网络请求Github开源项目

EitherNet

EitherNet 是一个多平台、可插拔且密封的 API 结果类型,用于建模网络 API 响应。目前,它仅在 JVM 上为 Retrofit 实现,但核心 API 定义在公共代码中,可以为其他平台实现。

以下 README 内容主要关注 Retrofit 实现。

使用方法

默认情况下,Retrofit 使用异常来传播错误。本库利用 Kotlin 密封类型来更好地模型化这些响应,提供类型安全的单一返回点,无需异常处理!

核心类型是 ApiResult<out T, out E>,其中 T 是成功类型,E 是可能的错误类型。

ApiResult 有两个密封子类型:SuccessFailureSuccess 类型为 T,没有错误类型;Failure 类型为 E,没有成功类型。Failure 又有四个密封子类型:Failure.NetworkFailureFailure.ApiFailureFailure.HttpFailureFailure.UnknownFailure。这允许通过一致的、非异常流程使用密封 when 分支简单处理结果。

when (val result = myApi.someEndpoint()) { is Success -> doSomethingWith(result.response) is Failure -> when (result) { is NetworkFailure -> showError(result.error) is HttpFailure -> showError(result.code) is ApiFailure -> showError(result.error) is UnknownFailure -> showError(result.error) } }

通常,用户代码只需为 Failure 情况显示一个通用错误消息,但密封子类型也允许更具体的错误消息或错误类型的可插拔性。

只需将端点返回类型更改为类型化的 ApiResult,并包含我们的调用适配器和委托转换器工厂。

interface TestApi { @GET("/") suspend fun getData(): ApiResult<SuccessResponse, ErrorResponse> } val api = Retrofit.Builder() .addConverterFactory(ApiResultConverterFactory) .addCallAdapterFactory(ApiResultCallAdapterFactory) .build() .create<TestApi>()

如果没有自定义错误返回类型,只需将错误类型设为 Unit

解码错误主体

如果要解码 HttpFailure 中的错误类型,请使用 @DecodeErrorBody 注解标记端点:

interface TestApi { @DecodeErrorBody @GET("/") suspend fun getData(): ApiResult<SuccessResponse, ErrorResponse> }

现在,4xx 或 5xx 响应将尝试将其错误主体(如果有)解码为 ErrorResponse。如果要根据状态码上下文解码错误主体,可以在自定义 Retrofit Converter 中从注解中检索 @StatusCode 注解。

// 在您自己的转换器工厂中 override fun responseBodyConverter( type: Type, annotations: Array<out Annotation>, retrofit: Retrofit ): Converter<ResponseBody, *>? { val (statusCode, nextAnnotations) = annotations.statusCode() ?: return null val errorType = when (statusCode.value) { 401 -> Unauthorized::class.java 404 -> NotFound::class.java // ... } val errorDelegate = retrofit.nextResponseBodyConverter<Any>(this, errorType.toType(), nextAnnotations) return MyCustomBodyConverter(errorDelegate) }

注意,内容长度为 0 的错误主体将被跳过。

可插拔性

某些 API 的常见模式是返回多态的 200 响应,其中数据需要动态解析。考虑以下示例:

{ "ok": true, "data": { ... } }

同一 API 在错误事件中可能返回这种结构:

{ "ok": false, "error_message": "请重试。" }

这很难用单一具体类型建模,但使用 ApiResult 很容易处理。只需在自定义 Retrofit Converter 中抛出带有解码错误类型的 ApiException,它将自动作为带有该错误实例的 Failure.ApiFailure 类型呈现。

@GET("/") suspend fun getData(): ApiResult<SuccessResponse, ErrorResponse> // 在您自己的转换器工厂中 class ErrorConverterFactory : Converter.Factory() { override fun responseBodyConverter( type: Type, annotations: Array<out Annotation>, retrofit: Retrofit ): Converter<ResponseBody, *>? { // 这返回一个 `@ResultType` 实例,可用于通过 toType() 获取错误类型 val (errorType, nextAnnotations) = annotations.errorType() ?: return null return ResponseBodyConverter(errorType.toType()) } class ResponseBodyConverter( private val errorType: Type ) : Converter<ResponseBody, *> { override fun convert(value: ResponseBody): String { if (value.isErrorType()) { val errorResponse = ... throw ApiException(errorResponse) } else { return SuccessResponse(...) } } } }

重试

网络请求的一个常见模式是使用指数退避进行重试。EitherNet 提供了一个高度可配置的 retryWithExponentialBackoff() 函数用于这种情况。

// 默认值供参考 val result = retryWithExponentialBackoff( maxAttempts = 3, initialDelay = 500.milliseconds, delayFactor = 2.0, maxDelay = 10.seconds, jitterFactor = 0.25, onFailure = null, // 可选的失败回调,用于日志记录 ) { api.getData() }

测试

EitherNet 提供了一个 测试夹具 工件,其中包含 EitherNetController API,允许轻松测试 EitherNet API。这类似于 OkHttp 的 MockWebServer,可以为特定端点排队结果。

只需在测试中使用 newEitherNetController() 函数之一创建一个新的控制器实例。

val controller = newEitherNetController<PandaApi>() // 具体化类型

然后,您可以从中访问底层模拟的 api 属性,并将其传递给被测试的对象。

// 从控制器获取 api 实例并传递给被测试的对象 val provider = PandaDataProvider(controller.api)

最后,根据需要为端点排队结果。

// 在测试中,您可以为特定端点排队结果 controller.enqueue(PandaApi::getPandas, ApiResult.success("Po"))

您还可以选择传入完整的挂起函数,如果需要动态行为:

controller.enqueue(PandaApi::getPandas) { // 这是一个挂起函数! delay(1000) ApiResult.success("Po") }

在使用依赖注入的集成测试中,您可以在测试模块中提供控制器及其底层 API,并替换标准模块。这与 Anvil 配合得特别好。

@ContributesTo( scope = UserScope::class, replaces = [PandaApiModule::class] // 替换标准模块 ) @Module object TestPandaApiModule { @Provides fun providePandaApiController(): EitherNetController<PandaApi> = newEitherNetController() @Provides fun providePandaApi( controller: EitherNetController<PandaApi> ): PandaApi = controller.api }

然后,您可以在测试中注入控制器,而 PandaApi 的用户将获得您的测试实例。

Java 互操作性

对于 Java 互操作性,JavaEitherNetControllers.enqueueFromJava 提供了有限的 API。

验证

EitherNetController 会在后台对 API 端点进行一些小型验证。如果您想在此基础上添加自己的验证,可以通过 ServiceLoader 提供 ApiValidator 的实现。有关更多信息,请参阅 ApiValidator 的文档。

安装

Maven Central

dependencies { implementation("com.slack.eithernet:eithernet:<版本>") implementation("com.slack.eithernet:eithernet-integration-retrofit:<版本>") // 测试夹具 testImplementation(testFixtures("com.slack.eithernet:eithernet:<版本>")) }

开发版本的快照可在 Sonatype 的 snapshots 仓库中获得。

许可证

Copyright 2020 Slack Technologies, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

编辑推荐精选

Vora

Vora

免费创建高清无水印Sora视频

Vora是一个免费创建高清无水印Sora视频的AI工具

Refly.AI

Refly.AI

最适合小白的AI自动化工作流平台

无需编码,轻松生成可复用、可变现的AI自动化工作流

酷表ChatExcel

酷表ChatExcel

大模型驱动的Excel数据处理工具

基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。

AI工具酷表ChatExcelAI智能客服AI营销产品使用教程
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
AIWritePaper论文写作

AIWritePaper论文写作

AI论文写作指导平台

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

AI辅助写作AI工具AI论文工具论文写作智能生成大纲数据安全AI助手热门
博思AIPPT

博思AIPPT

AI一键生成PPT,就用博思AIPPT!

博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。

AI办公办公工具AI工具博思AIPPTAI生成PPT智能排版海量精品模板AI创作热门
潮际好麦

潮际好麦

AI赋能电商视觉革命,一站式智能商拍平台

潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。

iTerms

iTerms

企业专属的AI法律顾问

iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。

SimilarWeb流量提升

SimilarWeb流量提升

稳定高效的流量提升解决方案,助力品牌曝光

稳定高效的流量提升解决方案,助力品牌曝光

Sora2视频免费生成

Sora2视频免费生成

最新版Sora2模型免费使用,一键生成无水印视频

最新版Sora2模型免费使用,一键生成无水印视频

下拉加载更多