0

I calling to the api with the basic retrofit Call object:

public interface dataApi {
    @GET("animal/cats")
    Call<AllAnimals> getAllData(
            @Query("api_key") String apiKey
    );
}

And I can get the response inside my view model like this:

  call.enqueue(new Callback<AllAnimals>() {

      @Override
      public void onResponse(Call<AllAnimals> call, Response<AllAnimals> response) {
          animals.setValue(response.body());
      }

      @Override
      public void onFailure(Call<AllAnimals> call, Throwable t) {
          Log.i(TAG, "onFailure: " + t);

      }
  });

Nothing speical here.

I've several problem with this approach

FIRST - if I give the wrong api key for example, the response should give me a response with the code of the problem, instead I just get null body.

SECOND I am planning to have more api calls, and it's a huge code duplication to handle errors every call I wrote.

How can I implement custom error handling for this situation, that will be apply to other calls too?

Noam
  • 485
  • 1
  • 7
  • 18

1 Answers1

1

I think you can use okhttp interceptor and define yourself ResponseBody converter to fix your problem.

  • First,intercept you interested request and response;
  • Second,check the response,if response is failed then modify the response body to empty。

define a simple interceptor

Interceptor interceptor = new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        String url = request.url().toString();
        System.out.println(request.url());
        okhttp3.Response response = chain.proceed(request);

        if (!response.isSuccessful() && url.contains("animal/cats")) {
            // request failed begin to modify response body
            response = response.newBuilder()
                .body(ResponseBody.create(MediaType.parse("application/json"), new byte[] {}))
                .build();
        }

        return response;
    }
};

define self ResponseBody converter

most code from com.squareup.retrofit2:converter-jackson we just add two lines:

final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final ObjectReader adapter;

    JacksonResponseBodyConverter(ObjectReader adapter) {
        this.adapter = adapter;
    }

    @Override public T convert(ResponseBody value) throws IOException {
        try {
            if (value.contentLength() == 0) {
                return null;
            }
            return adapter.readValue(value.charStream());
        } finally {
            value.close();
        }
    }
}

the below code is added:

if (value.contentLength() == 0) {
    return null;
}
TongChen
  • 1,414
  • 1
  • 11
  • 21