在我的应用程序中,我使用 Retrofit 库连接到服务器,有时会显示验证错误或其他原因......
报错信息格式如下:
{
"message": "The given data was invalid.",
"errors": {
"login": [
"Email or phone is not valid"
]
}
}
login 对象在其他 API 中发生变化,可能显示 password、basket 或其他...
我知道我可以使用上面的 Json 创建错误类并使用 Gson 库转换 errorBody 并显示它!
但我不想为每个 API 创建一个新类!
我想创建一个通用类并从 Json 的错误字段中获取所有错误消息并将其显示给用户!
我的网络响应类:
open class NetworkResponse<T>(private val response: Response<T>) {
fun generalNetworkResponse(): NetworkRequest<T> {
return when {
response.code() == 401 -> NetworkRequest.Error("You are not authorized")
response.code() == 422 -> NetworkRequest.Error("Api key not found!")
response.code() == 500 -> NetworkRequest.Error("Try again")
response.isSuccessful -> NetworkRequest.Success(response.body()!!)
else -> NetworkRequest.Error(response.message())
}
}
}
Config改造代码:
@Module
@InstallIn(SingletonComponent::class)
object NetworkProviders {
@Provides
@Singleton
fun provideBaseUrl() = BASE_URL
@Provides
@Singleton
fun provideNetworkTime() = CONNECTION_TIME
@Provides
@Singleton
fun provideGson(): Gson = GsonBuilder().setLenient().create()
@Provides
@Singleton
fun provideInterceptor() = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
@Provides
@Singleton
fun provideClient(time: Long, interceptor: HttpLoggingInterceptor) = OkHttpClient.Builder()
.addInterceptor(interceptor)
.writeTimeout(time, TimeUnit.SECONDS)
.readTimeout(time, TimeUnit.SECONDS)
.connectTimeout(time, TimeUnit.SECONDS)
.build()
@Provides
@Singleton
fun provideRetrofit(baseUrl: String, gson: Gson, client: OkHttpClient): ApiServices =
Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(ApiServices::class.java)
}
如何使用 Retrofit 动态处理错误?
创建一个名为 ApiError
的类data class ApiError(
val message: String?,
val errors: Map<String, List<String>>?
)
在您的 Retrofit Callback 实现中,您可以使用 Gson 库将错误响应解析为 ApiError 的实例。这是一个例子:
class MyCallback : Callback<MyResponse> {
override fun onResponse(call: Call<MyResponse>, response: Response<MyResponse>) {
// handle success response...
}
override fun onFailure(call: Call<MyResponse>, t: Throwable) {
// handle network error...
}
override fun onFailure(call: Call<MyResponse>, response: Response<MyResponse>) {
if (response.errorBody() != null) {
try {
val apiError = Gson().fromJson(response.errorBody()!!.string(), ApiError::class.java)
// handle API error...
val errorMessage = apiError.message
val errors = apiError.errors
// You can iterate through the map of errors and display them to the user
errors?.forEach { (field, fieldErrors) ->
// display field errors to user
}
} catch (e: IOException) {
// handle parsing error...
}
} else {
// handle unexpected error...
}
}
}