Android中如何使用Retrofit适配非HTTP类请求/响应协议
可行方案说明
完全可以脱离OkHttp使用Retrofit对接自定义协议,核心误区是不要把请求适配的逻辑寄希望于CallAdapter——CallAdapter仅负责将Retrofit的请求对象适配为你需要的返回类型(比如协程挂起函数、RxJava观察者等),真正控制底层请求逻辑的是Call.Factory接口,你看到的client(OkHttpClient)方法本质只是传入了OkHttp对该接口的官方实现,并非硬绑定。
具体实现步骤
- 自定义协议对应的
Call实现
实现Retrofit内置的Call接口,在execute()(同步请求)、enqueue()(异步回调)方法内部直接调用你现有的IoT协议执行器,将协议返回的结果映射为Retrofit要求的Response对象即可。由于你的协议架构和HTTP高度相似,状态码、请求头、请求体、响应体的映射成本极低。同时实现cancel()、isExecuted()、isCanceled()、clone()几个状态控制方法即可。 - 自定义
Call.Factory实现
实现Call.Factory接口的newCall(Request)方法:方法入参是Retrofit解析接口注解(比如@GET、@POST、@Path、@Query、@Body这些标准注解可以直接复用,只要语义和你的协议匹配)生成的请求元数据,包含所有请求参数、路径、请求体信息,你只需要在这个方法里返回上一步自定义的Call实例,将Request携带的信息转换为你的IoT协议需要的请求格式即可。 - 初始化Retrofit时传入自定义工厂
不要调用client(OkHttpClient)方法,而是调用Builder的公开方法callFactory()传入你自定义的Call.Factory实例。如果你的协议有HTTP标准注解覆盖不到的特殊参数,还可以自定义专属请求注解,在自定义工厂里读取注解参数即可。
注意事项
- 如果你完全不需要OkHttp能力,可以直接在构建依赖时排除OkHttp的传递依赖,Retrofit的核心注解解析、序列化/反序列化、类型适配能力都不依赖OkHttp,可独立运行。
- 响应转换器(比如Gson、Moshi的ConverterFactory)、返回类型适配器(比如协程、RxJava的CallAdapter.Factory)都可以照常使用,和对接HTTP时没有任何差异。
- 如果你没有自定义
Call.Factory,Retrofit Builder才会默认创建一个OkHttpClient实例作为兜底,这个逻辑只是默认配置,不是核心层的强绑定,不需要反射或者修改源码就能绕过。
极简实现示例
// 自定义Call实现,对接自有IoT执行器 class IotProtocolCall( private val request: Request, private val iotExecutor: IotProtocolExecutor ) : Call<Any> { override fun execute(): Response<Any> { // 将Retrofit解析出的Request转换为自有协议的请求格式 val iotReq = convertRetrofitRequestToIotFormat(request) // 调用自有执行器发起请求 val iotResp = iotExecutor.syncRequest(iotReq) // 将自有协议响应转换为Retrofit的Response格式 return Response.success( convertIotRespToBody(iotResp), buildHeadersFromIotResp(iotResp) ) } override fun enqueue(callback: Callback<Any>) { // 异步请求实现逻辑,内部调用iotExecutor的异步方法,结果通过callback回调即可 } override fun cancel() { /* 实现请求取消逻辑 */ } override fun isExecuted(): Boolean = /* 返回请求是否已执行 */ false override fun isCanceled(): Boolean = /* 返回请求是否已取消 */ false override fun clone(): Call<Any> = /* 实现Call拷贝逻辑 */ IotProtocolCall(request, iotExecutor) override fun request(): Request = request } // 自定义Call.Factory class IotCallFactory( private val iotExecutor: IotProtocolExecutor ) : Call.Factory { override fun newCall(request: Request): Call = IotProtocolCall(request, iotExecutor) } // 初始化Retrofit val retrofit = Retrofit.Builder() .baseUrl("iot://device-endpoint/") // 符合URI规范的自有协议根地址即可 .addConverterFactory(GsonConverterFactory.create()) // 序列化转换器正常使用 .addCallAdapterFactory(CoroutineCallAdapterFactory()) // 返回类型适配器正常使用 .callFactory(IotCallFactory(yourExistingIotExecutor)) // 传入自定义工厂,完全不依赖OkHttp .build()
内容的提问来源于stack exchange,提问作者Josué RL
相关产品推荐
相关产品推荐

