如何在Retrofit的onFailure()中获取请求方法、端点及提交字段值
Retrofit错误追踪:获取请求方法、端点及提交字段
需求说明
我希望追踪所有Retrofit请求的错误,需要记录出现问题的请求方法、端点名称以及用户提交的字段值。
相关代码
UserServices.java
@GET("visit/current_checkin") Call<ResponCurrentCheckIn> getCurrentCheckin( @Query("sdo_id") String sdoId );
Retrofit调用代码
new ApiClient().getUserService(SplashActivity.this).getCurrentCheckin(sdoId) .enqueue(new Callback<ResponCurrentCheckIn>() { @Override public void onResponse(Call<ResponCurrentCheckIn> call, Response<ResponCurrentCheckIn> response) { if (response.isSuccessful()) { // TODO } } @Override public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) { String message = t.getClass().getSimpleName() + "\n" + t.getMessage(); loading(false, message); new LogTracking(SplashActivity.this).save(user, "SplashActivity.java", "GET /visit/current_checkin", t.getMessage(), "Error Backend", null); } });
ApiClient.java
public static Retrofit retrofit; // public static final String BASE_URL = "https://online.meval.id/v1/api/"; // public static final String BASE_URL = "https://v2.meval.id/v1/api/"; public static Retrofit getRetrofitInstance(String baseUrl) { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Request newRequest = originalRequest.newBuilder() .header("Accept", "application/json") .header("Content-Type", "application/x-www-form-urlencoded") .header("Authtoken", "MY-AUTHTOKEN") .build(); return chain.proceed(newRequest); } }) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) .connectTimeout(60, TimeUnit.SECONDS) .addInterceptor(httpLoggingInterceptor) .build(); if (retrofit == null) { retrofit = new Retrofit.Builder() .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .baseUrl(baseUrl) .client(okHttpClient) .build(); } return retrofit; } public static UserServices getUserService(Context context){ SharedPreferences preferences = context.getSharedPreferences(MyPreference.CONTAINER_PREFERENCE.toString(), Context.MODE_PRIVATE); UserServices userService = getRetrofitInstance(BASE_URL).create(UserServices.class); return userService; }
问题
- 如何在
onFailure()中获取请求方法名?例如:GET、POST、PUT等 - 如何在
onFailure()中获取端点名称?例如:/visit/current_checkin - 如何在
onFailure()中获取用户提交的各字段值?例如:sdoId的值
我尝试通过Android Studio提示访问Throwable类,但未找到相关方法。
解决方案
1. 获取请求方法名
Retrofit的Call对象可关联到OkHttp的Request,通过request().method()直接拿到请求方法:
@Override public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) { String method = call.request().method(); // 得到GET/POST/PUT等 // 后续日志记录逻辑 }
2. 获取端点名称
方式一:从URL中截取
从Request拿到HttpUrl,结合BaseUrl截取相对路径:
@Override public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) { HttpUrl url = call.request().url(); String baseUrl = ApiClient.getRetrofitInstance(ApiClient.BASE_URL).baseUrl().toString(); String endpoint = url.toString().replace(baseUrl, ""); // 得到/visit/current_checkin // 后续日志记录逻辑 }
方式二:通过Interceptor提前存入Tag
修改ApiClient中的Interceptor,将端点信息存入Request的Tag,后续直接读取:
.addInterceptor(new Interceptor() { @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); // 提取端点路径 String endpoint = originalRequest.url().encodedPath(); // 将端点存入request的tag Request newRequest = originalRequest.newBuilder() .header("Accept", "application/json") .header("Content-Type", "application/x-www-form-urlencoded") .header("Authtoken", "MY-AUTHTOKEN") .tag("endpoint", endpoint) .build(); return chain.proceed(newRequest); } })
在onFailure中获取:
String endpoint = (String) call.request().tag("endpoint");
3. 获取用户提交的字段值
方式一:调用时直接保留参数引用
在发起请求时保存需要记录的参数,在onFailure中直接使用:
final String currentSdoId = sdoId; // 保存参数引用 new ApiClient().getUserService(SplashActivity.this).getCurrentCheckin(currentSdoId) .enqueue(new Callback<ResponCurrentCheckIn>() { @Override public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) { // 直接使用currentSdoId new LogTracking(SplashActivity.this).save(user, "SplashActivity.java", "GET /visit/current_checkin", t.getMessage(), "Error Backend", currentSdoId); } });
方式二:从Request中解析参数
如果是GET请求,参数在URL的Query里,可通过HttpUrl的queryParameter方法获取:
@Override public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) { HttpUrl url = call.request().url(); String sdoId = url.queryParameter("sdo_id"); // 其他参数用对应的key获取 }
如果是POST请求(表单或JSON),可在Interceptor中提前解析请求体并存入Tag,或使用OkHttp的工具类读取RequestBody内容。
内容的提问来源于stack exchange,提问作者Sasmita Novitasari
相关产品推荐
相关产品推荐

