Retrofit返回Response<Void>时非200状态码不触发异常的注解方案问询
解决Retrofit返回Response时非200状态码不触发异常的问题
Retrofit本身没有内置注解能让返回Response类型的接口自动抛出包含Response对象的异常——因为Retrofit的设计逻辑就是:当方法返回Response时,无论HTTP状态码是否成功,都会将结果封装为Response对象返回,不会主动抛出HttpException,所以你的catch分支无法触发。
不过可以通过以下两种方式实现需求:
1. 手动判断状态码,主动抛出异常
这是最直接的方式,在调用接口后手动检查Response.isSuccessful,如果为false就抛出Retrofit自带的HttpException(该类内部持有原始的Response对象):
try { val response = sendTest(testModel) if (!response.isSuccessful) { throw HttpException(response) } // 处理成功逻辑 } catch (e: HttpException) { // 在这里通过e.response()获取原始Response val errorResponse = e.response() // 处理错误逻辑 }
2. 自定义注解+CallAdapter,实现全局/按需自动抛异常
如果想让指定接口自动在非成功状态码时抛异常,可以自定义一个注解,配合自定义CallAdapter.Factory来实现:
步骤1:定义自定义注解
@Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) annotation class ThrowOnError
步骤2:实现自定义CallAdapter.Factory
这个CallAdapter会拦截接口调用,判断方法是否带有@ThrowOnError注解,若是则在非成功状态码时自动抛出HttpException:
class ThrowOnErrorCallAdapterFactory : CallAdapter.Factory() { override fun get( returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit ): CallAdapter<*, *>? { // 先获取Retrofit默认的CallAdapter val delegate = retrofit.nextCallAdapter(this, returnType, annotations) // 判断当前接口方法是否带有@ThrowOnError注解 val shouldThrow = annotations.any { it is ThrowOnError } return object : CallAdapter<Any, Call<Any>> { override fun responseType(): Type = delegate.responseType() override fun adapt(call: Call<Any>): Call<Any> { return object : Call<Any> by call { // 处理挂起函数的await逻辑 override suspend fun await(): Any { val response = call.await() if (shouldThrow && response is Response<*> && !response.isSuccessful) { throw HttpException(response as Response<*>) } return response } // 处理传统的enqueue回调逻辑(如果有用到的话) override fun enqueue(callback: Callback<Any>) { call.enqueue(object : Callback<Any> { override fun onResponse(call: Call<Any>, response: Response<Any>) { if (shouldThrow && !response.isSuccessful) { callback.onFailure(call, HttpException(response)) } else { callback.onResponse(call, response) } } override fun onFailure(call: Call<Any>, t: Throwable) { callback.onFailure(call, t) } }) } } } } } }
步骤3:在Retrofit构建时添加该CallAdapterFactory
val retrofit = Retrofit.Builder() .baseUrl("your_base_url") .addCallAdapterFactory(ThrowOnErrorCallAdapterFactory()) .addConverterFactory(GsonConverterFactory.create()) .build()
步骤4:在接口方法上添加自定义注解
@POST("/test") @ThrowOnError suspend fun sendTest(@Body model: TestModel): Response<Void>
这样,当这个接口返回非200状态码时,会自动抛出HttpException,你可以在catch分支中通过e.response()拿到原始的Response对象。
内容的提问来源于stack exchange,提问作者user1854307
相关产品推荐
相关产品推荐

