I have seen many articles and questions about error handling using retrofit in combination with RxAndroid, but I canβt configure my configuration correctly.
What I want to do:
- when receiving 4xx code: handle it onError ()
when receiving a 2xx code:
-> try to parse the expected response and deliver it toNext ()
-> If this is not possible, try converting the JSON response to the MyAPIError class (simple POJO with errorNum and message) and deliver it to onError.
Thus, both 2xx or 4xx http codes can end up in onError ().
What I have at the moment:
ServiceGenerator.java
public class ServiceGenerator { private static final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY); private static final Gson gson = new GsonBuilder() .registerTypeAdapter(DateTime.class, (JsonDeserializer<DateTime>) (json, typeOfT, context) -> new DateTime(json.getAsJsonPrimitive().getAsLong())).create(); public static Retrofit buildRetrofit() { return new Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .baseUrl("....myURL...") .client(getOkHttpClient()).build(); } private static OkHttpClient getOkHttpClient() { return new OkHttpClient.Builder() .addInterceptor(interceptor) .addInterceptor(chain -> { Request request = chain.request().newBuilder() .addHeader(ProductionSettings.HEADER_KEY_TOKEN, "myToken here") .build(); return chain.proceed(request); }) .followRedirects(true) .followSslRedirects(true) .build(); } public static <S> S createService(final Class<S> serviceClass) { return buildRetrofit().create(serviceClass); } }
NetworkComunnication.java
public class NetworkCommunication implements UserAPI { private static NetworkCommunication instance; private final UserAPI userAPI; private NetworkCommunication() { this.userAPI = ServiceGenerator.createService(UserAPI.class); } public static NetworkCommunication getInstance() { if (instance == null) { instance = new NetworkCommunication(); } return instance; } @Override public Observable<UserResponse> updateUser(@Path(UsersSchema.ObjectId) String objectId, @Body final Map<String, Object> body) { return userAPI.updateUser(objectId, body); } }
UserIteractor.java
public class UserIteractor { private final UserMapper mapper; public UserIteractor() { this.mapper = new UserMapper(); } public Observable<Boolean> updateUser(Long userObjectID, UserViewModel model) { Map<String, Object> reqBody = mapper.mapToUpdateRequestBody(model); return NetworkCommunication .getInstance() .updateUser(userObjectID, reqBody) .map(prodUserResponse -> true); } }
I would like to process everything before it gets into the UserInteractor class, so it would be common for all Interactors, and I would not have to do the same logic for all requests. How can I get this to be as general as possible, and how can I be βon topβ?
Bugdr0id
source share