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()
}
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();
}
}
}