如何在Android中用Retrofit简化网络响应处理的重复代码?
优化重复响应处理逻辑的方案
你当前在多个ViewModel中重复编写类似的响应处理方法,产生了大量样板代码,可以通过以下几种方式实现代码复用,保持整洁:
1. 提取泛型工具类
将通用的响应处理逻辑封装到一个独立的工具类中,利用泛型支持不同类型的Response和Resource:
object ApiResponseHandler { // 全局复用Gson实例,避免重复创建带来的性能损耗 private val gson = Gson() fun <T> handleResponse(response: Response<T>): Resource<T> { return if (response.isSuccessful) { // 处理成功响应 response.body()?.let { Resource.Success(it) } ?: Resource.Failure("Response body is null") } else { // 解析错误体 val errorBody = response.errorBody()?.charStream()?.let { gson.fromJson(it, ErrorBodyResponse::class.java) } // 根据状态码匹配错误信息 val errorTitle = when(response.code()) { 400 -> Constants.error400 401 -> Constants.error401 403 -> Constants.error403 408 -> Constants.error408 413 -> Constants.error413 511 -> Constants.error511 else -> "Something went wrong" } Resource.Failure(errorTitle, errorBody?.message) } } }
使用方式
在ViewModel中直接调用工具类的方法,无需重复编写处理逻辑:
private fun handleResponse(response: Response<OtpSentDataClass>): Resource<OtpSentDataClass> { return ApiResponseHandler.handleResponse(response) } private fun handleDeviceDetailResponse(response: Response<DeviceDetailResponse>): Resource<DeviceDetailResponse> { return ApiResponseHandler.handleResponse(response) }
2. 给Response添加扩展函数
利用Kotlin的扩展函数特性,直接给Retrofit的Response<T>类添加转换为Resource<T>的方法,进一步简化调用:
// 全局复用Gson实例 private val gson = Gson() fun <T> Response<T>.toResource(): Resource<T> { return if (this.isSuccessful) { this.body()?.let { Resource.Success(it) } ?: Resource.Failure("Response body is null") } else { val errorBody = this.errorBody()?.charStream()?.let { gson.fromJson(it, ErrorBodyResponse::class.java) } val errorTitle = when(this.code()) { 400 -> Constants.error400 401 -> Constants.error401 403 -> Constants.error403 408 -> Constants.error408 413 -> Constants.error413 511 -> Constants.error511 else -> "Something went wrong" } Resource.Failure(errorTitle, errorBody?.message) } }
使用方式
在网络请求回调中直接调用扩展方法,无需额外编写handleXXX方法:
// 示例:网络请求回调 fun fetchOtp() { viewModelScope.launch { val response = apiService.sendOtp(...) val resource = response.toResource() // 后续处理resource(更新UI状态等) } }
3. 基于基类ViewModel封装通用逻辑
如果所有需要处理响应的ViewModel都可以继承一个基类,可将通用逻辑放在基类中:
open class BaseViewModel : ViewModel() { private val gson = Gson() // 受保护方法,子类可直接调用 protected fun <T> handleApiResponse(response: Response<T>): Resource<T> { return if (response.isSuccessful) { response.body()?.let { Resource.Success(it) } ?: Resource.Failure("Response body is null") } else { val errorBody = response.errorBody()?.charStream()?.let { gson.fromJson(it, ErrorBodyResponse::class.java) } val errorTitle = when(response.code()) { 400 -> Constants.error400 401 -> Constants.error401 403 -> Constants.error403 408 -> Constants.error408 413 -> Constants.error413 511 -> Constants.error511 else -> "Something went wrong" } Resource.Failure(errorTitle, errorBody?.message) } } }
使用方式
让你的ViewModel继承BaseViewModel,直接调用基类的通用方法:
class AuthViewModel : BaseViewModel() { private fun handleOtpResponse(response: Response<OtpSentDataClass>): Resource<OtpSentDataClass> { return handleApiResponse(response) } }
内容的提问来源于stack exchange,提问作者Ashish Gautam
相关产品推荐
相关产品推荐

