Search code examples
javaretrofit2future

Retrofit 2 with java 7 future


Is there any way to use retrofit 2 with java 7 futures (not java 8 completablefutures)?

Something along the lines of

interface MyService {
  GET("somepath")
  Future<User> getUser()
}

Solution

  • You should be able to create an adapter similar to Java8CallAdapterFactory.java. It would look something like:

    public class Java7CallAdapterFactory extends CallAdapter.Factory {
    
        public static Java7CallAdapterFactory create() {
            return new Java7CallAdapterFactory();
        }
    
        @Override
        public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
            // TODO: Check type of returnType and innerType, null checks, etc ...
            Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
            return new BodyCallAdapter<R>(responseType);
        }
    
        private static final class BodyCallAdapter<R> implements CallAdapter<R, Future<R>> {
            private final Type responseType;
    
            BodyCallAdapter(Type responseType) {
                this.responseType = responseType;
            }
    
            @Override public Type responseType() {
                return responseType;
            }
    
            @Override public Future<R> adapt(final Call<R> call) {
                final Java7Future<R> future = new Java7Future<>(call);
    
                call.enqueue(new Callback<R>() {
                    @Override 
                    public void onResponse(Call<R> call, Response<R> response) {
                        if (response.isSuccessful()) {
                            future.complete(response.body());
                        } // TODO: else
                    }
    
                    @Override 
                    public void onFailure(Call<R> call, Throwable t) {
                        // TODO
                    }
                });
    
                return future;
            }
        }
    
        private static class Java7Future<R> implements Future<R> {
            private Call<R> call;
            private boolean completed = false;
            private R value;
    
            public Java7Future(Call<R> call) {
                this.call = call;
            }
    
            public void complete(R result) {
                completed = true;
                value = result;
            }
    
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                if (call != null) {
                    call.cancel();
                }
                return false;
            }
    
            @Override
            public boolean isCancelled() {
                return call == null || call.isCanceled();
            }
    
            @Override
            public boolean isDone() {
                return completed;
            }
    
            @Override
            public R get() {
                if (isCancelled()) {
                    throw new CancellationException();
                } else {
                    // TODO: wait
                    return value;
                }
            }
    
            @Override
            public R get(long timeout, @NonNull TimeUnit unit) {
                // TODO: wait
                return get();
            }
        }
    }