Skip to content

Instantly share code, notes, and snippets.

@NightlyNexus
Created November 28, 2016 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NightlyNexus/e4dbbf714c671a15b846580f0b1f2241 to your computer and use it in GitHub Desktop.
Save NightlyNexus/e4dbbf714c671a15b846580f0b1f2241 to your computer and use it in GitHub Desktop.
public final class AutoRetryCallAdapterFactory extends CallAdapter.Factory {
final ArrayList<Action<?>> actions = new ArrayList<>();
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean connected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (!connected) {
return;
}
ArrayList<Action<?>> actions = new ArrayList<>(AutoRetryCallAdapterFactory.this.actions);
AutoRetryCallAdapterFactory.this.actions.clear();
for (int i = 0; i < actions.size(); i++) {
actions.get(i).run();
}
}
};
public void register(Context context) {
context.registerReceiver(receiver, new IntentFilter(CONNECTIVITY_ACTION));
}
public void unregister(Context context) {
actions.clear();
context.unregisterReceiver(receiver);
}
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
// noinspection unchecked
final CallAdapter<Call<?>> adapter =
(CallAdapter<Call<?>>) retrofit.nextCallAdapter(this, returnType, annotations);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return adapter.responseType();
}
@Override public <R> Call<?> adapt(Call<R> call) {
return adapter.adapt(new ActionAddingCall<>(call));
}
};
}
private final class ActionAddingCall<R> implements Call<R> {
private final Call<R> call;
ActionAddingCall(Call<R> call) {
this.call = call;
}
@Override public Response<R> execute() throws IOException {
return call.execute();
}
@Override public void enqueue(final Callback<R> callback) {
call.enqueue(new Callback<R>() {
@Override public void onResponse(Call<R> call, Response<R> response) {
callback.onResponse(call, response);
}
@Override public void onFailure(Call<R> call, Throwable t) {
callback.onFailure(call, t);
if (!call.isCanceled()) {
// ActionAddingCall.this.call == call
actions.add(new Action<>(call, callback));
}
}
});
}
@Override public boolean isExecuted() {
return call.isExecuted();
}
@Override public void cancel() {
call.cancel();
Iterator<Action<?>> iterator = actions.iterator();
while (iterator.hasNext()) {
if (iterator.next().call == call) {
iterator.remove();
}
}
}
@Override public boolean isCanceled() {
return call.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<R> clone() {
return new ActionAddingCall<>(call.clone());
}
@Override public Request request() {
return call.request();
}
}
private static final class Action<R> {
private final Call<R> call;
private final Callback<R> callback;
Action(Call<R> call, Callback<R> callback) {
this.call = call;
this.callback = callback;
}
void run() {
Callback<R> callback = this.callback;
if (callback != null) {
call.clone().enqueue(callback);
}
}
}
}
@NightlyNexus
Copy link
Author

This won't work because here https://gist.github.com/NightlyNexus/e4dbbf714c671a15b846580f0b1f2241#file-autoretrycalladapterfactory-java-L114 you will end up with a different Call in your Action and not be able to cancel it. This was just a hacked-together thing.
I need to try this with Rx.

@NightlyNexus
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment