Skip to content

Instantly share code, notes, and snippets.

@naturalwarren
Last active July 28, 2022 10:47
Show Gist options
  • Save naturalwarren/d1a053707fa1b9987c1b0ff12f399d23 to your computer and use it in GitHub Desktop.
Save naturalwarren/d1a053707fa1b9987c1b0ff12f399d23 to your computer and use it in GitHub Desktop.

Revisions

  1. naturalwarren revised this gist Jan 27, 2017. 2 changed files with 119 additions and 0 deletions.
    40 changes: 40 additions & 0 deletions NetworkException.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    package com.uber.retrofit2.adapters.network.exception;

    import android.support.annotation.NonNull;

    import java.io.IOException;

    import okhttp3.Call;
    import okhttp3.Callback;
    import okhttp3.Request;

    /**
    * Exception for unexpected, network errors.
    */
    public class NetworkException extends IOException {

    private final Request request;
    private final IOException ioException;

    public NetworkException(@NonNull Request request, @NonNull IOException ioException) {
    super(ioException.getMessage(), ioException.getCause());
    this.request = request;
    this.ioException = ioException;
    }

    /**
    * @return the {@link IOException} returned by {@link Call#execute()} or {@link Call#enqueue(Callback)}.
    */
    @NonNull
    public IOException ioException() {
    return ioException;
    }

    /**
    * @return the {@link Request} that resulted in an error at the network level.
    */
    @NonNull
    public Request request() {
    return request;
    }
    }
    79 changes: 79 additions & 0 deletions NetworkExceptionCall.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    package com.uber.retrofit2.adapters.network.exception;

    import android.support.annotation.NonNull;

    import java.io.IOException;

    import okhttp3.Request;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

    /**
    * An {@link Call} that delegates to a backing Call and returns {@link NetworkException} when an {@link IOException} is
    * encountered.
    * @param <T> Successful response body type.
    */
    final class NetworkExceptionCall<T> implements Call<T> {

    private final Call<T> delegateCall;

    NetworkExceptionCall(@NonNull Call<T> delegateCall) {
    this.delegateCall = delegateCall;
    }

    @Override
    public Response<T> execute() throws IOException {
    try {
    return delegateCall.execute();
    } catch (IOException e) {
    throw new NetworkException(request(), e);
    }
    }

    @Override
    public void enqueue(final Callback<T> callback) {
    delegateCall.enqueue(new Callback<T>() {
    @Override
    public void onResponse(Call<T> call, Response<T> response) {
    callback.onResponse(call, response);
    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {
    if (t instanceof IOException) {
    callback.onFailure(call, new NetworkException(request(), (IOException) t));
    } else {
    callback.onFailure(call, t);
    }
    }
    });
    }

    @Override
    public boolean isExecuted() {
    return delegateCall.isExecuted();
    }

    @Override
    public void cancel() {
    delegateCall.cancel();
    }

    @Override
    public boolean isCanceled() {
    return delegateCall.isCanceled();
    }

    // We are a final type & this saves clearing state.
    @SuppressWarnings("CloneDoesntCallSuperClone")
    @Override
    public Call<T> clone() {
    return new NetworkExceptionCall<>(delegateCall.clone());
    }

    @Override
    public Request request() {
    return delegateCall.request();
    }
    }
  2. naturalwarren created this gist Jan 27, 2017.
    56 changes: 56 additions & 0 deletions NetworkExceptionCallAdapterFactory.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    package com.uber.retrofit2.adapters.network.exception;

    import java.io.IOException;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Type;

    import okhttp3.Request;
    import retrofit2.Call;
    import retrofit2.CallAdapter;
    import retrofit2.Callback;
    import retrofit2.Retrofit;

    /**
    * A {@linkplain CallAdapter.Factory call adapter} that wraps {@link IOException} with its {@link Request}
    * in {@link NetworkException}.
    *
    * NOTE: This is a forwarding adapter and delegates to another call adapter. It must be registered to your
    * {@link Retrofit} instance before the adapter it delegates to.
    */
    public final class NetworkExceptionCallAdapterFactory extends CallAdapter.Factory {

    /**
    * @return an instance which will wrap any {@link IOException} with its corresponding {@link Request}.
    */
    public static NetworkExceptionCallAdapterFactory create() {
    return new NetworkExceptionCallAdapterFactory();
    }

    @Override
    public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    return new NetworkExceptionCallAdapter(retrofit.nextCallAdapter(this, returnType, annotations));
    }

    /**
    * Wraps a delegate call adapter and passes on a {@link NetworkExceptionCall} which performs
    * {@link IOException} wrapping when an error is encountered upon invoking
    * {@link NetworkExceptionCall#enqueue(Callback)} or {@link NetworkExceptionCall#execute()}.
    */
    private static final class NetworkExceptionCallAdapter implements CallAdapter<Object> {
    private final CallAdapter<?> delegateCallAdapter;

    NetworkExceptionCallAdapter(CallAdapter<?> delegateCallAdapter) {
    this.delegateCallAdapter = delegateCallAdapter;
    }

    @Override
    public Type responseType() {
    return delegateCallAdapter.responseType();
    }

    @Override
    public <R> Object adapt(Call<R> call) {
    return delegateCallAdapter.adapt(new NetworkExceptionCall<>(call));
    }
    }
    }