How can I add retry functionality to the requests sent by Retrofit 2 library. Something like:
service.listItems().enqueue(new Callback<List<Item>>() { @Override public void onResponse(Response<List<Item>> response) { ... } @Override public void onFailure(Throwable t) { ... } }).retryOnFailure(5 /* times */);
Now , retrofit does not come with retry support by default (although it was in their spec for their 2.0 release). If you are using Rx in your android app ,you can add the Retrofit Rx adapter and use RxJava observables for retrying.
OkHttp is a pure HTTP/SPDY client responsible for any low-level network operations, caching, requests and responses manipulation. In contrast, Retrofit is a high-level REST abstraction build on top of OkHttp. Retrofit is strongly coupled with OkHttp and makes intensive use of it.
Retrofit is a popular, simple and flexible library to handle network requests in android development.
I finally did something like this, for anyone interested:
First I made an abstract class CallbackWithRetry
public abstract class CallbackWithRetry<T> implements Callback<T> { private static final int TOTAL_RETRIES = 3; private static final String TAG = CallbackWithRetry.class.getSimpleName(); private final Call<T> call; private int retryCount = 0; public CallbackWithRetry(Call<T> call) { this.call = call; } @Override public void onFailure(Throwable t) { Log.e(TAG, t.getLocalizedMessage()); if (retryCount++ < TOTAL_RETRIES) { Log.v(TAG, "Retrying... (" + retryCount + " out of " + TOTAL_RETRIES + ")"); retry(); } } private void retry() { call.clone().enqueue(this); } }
Using this class I can do something like this:
serviceCall.enqueue(new CallbackWithRetry<List<Album>>(serviceCall) { @Override public void onResponse(Response<List<Album>> response) { ... } });
This is not completely satisfactory because I have to pass same serviceCall
twice. This can confusing as one can think the second serviceCall
(that goes into constructor of CallbackWithRetry
) should or could be something different from first one (which we invoke enqueue
method on it)
So I implemented a helper class CallUtils
:
public class CallUtils { public static <T> void enqueueWithRetry(Call<T> call, final Callback<T> callback) { call.enqueue(new CallbackWithRetry<T>(call) { @Override public void onResponse(Response<T> response) { callback.onResponse(response); } @Override public void onFailure(Throwable t) { super.onFailure(t); callback.onFailure(t); } }); } }
And I can use it like this:
CallUtils.enqueueWithRetry(serviceCall, new Callback<List<Album>>() { @Override public void onResponse(Response<List<Album>> response) { ... } @Override public void onFailure(Throwable t) { // Let the underlying method do the job of retrying. } });
With this I have to pass a standard Callback
to enqueueWithRetry
method and it makes me implement onFailure
(Though in the previous method I can implement it too)
So this is how I've solved the issue. Any suggestion for a better design would be appreciated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With