提交 45ef0b36 编写于 作者: J Jesse Wilson 提交者: GitHub

Merge pull request #2017 from square/jw/generics

Promote adapter response body type parameter to class level.
......@@ -57,7 +57,7 @@ public final class GuavaCallAdapterFactory extends CallAdapter.Factory {
}
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != ListenableFuture.class) {
return null;
}
......@@ -69,7 +69,7 @@ public final class GuavaCallAdapterFactory extends CallAdapter.Factory {
if (getRawType(innerType) != Response.class) {
// Generic type is not Response<T>. Use it for body-only adapter.
return new BodyCallAdapter(innerType);
return new BodyCallAdapter<>(innerType);
}
// Generic type is Response<T>. Extract T and create the Response version of the adapter.
......@@ -78,10 +78,10 @@ public final class GuavaCallAdapterFactory extends CallAdapter.Factory {
+ " as Response<Foo> or Response<? extends Foo>");
}
Type responseType = getParameterUpperBound(0, (ParameterizedType) innerType);
return new ResponseCallAdapter(responseType);
return new ResponseCallAdapter<>(responseType);
}
private static class BodyCallAdapter implements CallAdapter<ListenableFuture<?>> {
private static final class BodyCallAdapter<R> implements CallAdapter<R, ListenableFuture<R>> {
private final Type responseType;
BodyCallAdapter(Type responseType) {
......@@ -92,7 +92,7 @@ public final class GuavaCallAdapterFactory extends CallAdapter.Factory {
return responseType;
}
@Override public <R> ListenableFuture<R> adapt(final Call<R> call) {
@Override public ListenableFuture<R> adapt(final Call<R> call) {
return new AbstractFuture<R>() {
{
call.enqueue(new Callback<R>() {
......@@ -117,7 +117,8 @@ public final class GuavaCallAdapterFactory extends CallAdapter.Factory {
}
}
private static class ResponseCallAdapter implements CallAdapter<ListenableFuture<?>> {
private static final class ResponseCallAdapter<R>
implements CallAdapter<R, ListenableFuture<Response<R>>> {
private final Type responseType;
ResponseCallAdapter(Type responseType) {
......@@ -128,7 +129,7 @@ public final class GuavaCallAdapterFactory extends CallAdapter.Factory {
return responseType;
}
@Override public <R> ListenableFuture<Response<R>> adapt(final Call<R> call) {
@Override public ListenableFuture<Response<R>> adapt(final Call<R> call) {
return new AbstractFuture<Response<R>>() {
{
call.enqueue(new Callback<R>() {
......
......@@ -72,7 +72,7 @@ public final class GuavaCallAdapterFactoryTest {
}
@Test public void nonListenableFutureReturnsNull() {
CallAdapter<?> adapter = factory.get(String.class, NO_ANNOTATIONS, retrofit);
CallAdapter<?, ?> adapter = factory.get(String.class, NO_ANNOTATIONS, retrofit);
assertThat(adapter).isNull();
}
......
......@@ -56,7 +56,7 @@ public final class Java8CallAdapterFactory extends CallAdapter.Factory {
}
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != CompletableFuture.class) {
return null;
}
......@@ -68,7 +68,7 @@ public final class Java8CallAdapterFactory extends CallAdapter.Factory {
if (getRawType(innerType) != Response.class) {
// Generic type is not Response<T>. Use it for body-only adapter.
return new BodyCallAdapter(innerType);
return new BodyCallAdapter<>(innerType);
}
// Generic type is Response<T>. Extract T and create the Response version of the adapter.
......@@ -77,10 +77,10 @@ public final class Java8CallAdapterFactory extends CallAdapter.Factory {
+ " as Response<Foo> or Response<? extends Foo>");
}
Type responseType = getParameterUpperBound(0, (ParameterizedType) innerType);
return new ResponseCallAdapter(responseType);
return new ResponseCallAdapter<>(responseType);
}
private static class BodyCallAdapter implements CallAdapter<CompletableFuture<?>> {
private static final class BodyCallAdapter<R> implements CallAdapter<R, CompletableFuture<R>> {
private final Type responseType;
BodyCallAdapter(Type responseType) {
......@@ -91,7 +91,7 @@ public final class Java8CallAdapterFactory extends CallAdapter.Factory {
return responseType;
}
@Override public <R> CompletableFuture<R> adapt(final Call<R> call) {
@Override public CompletableFuture<R> adapt(final Call<R> call) {
final CompletableFuture<R> future = new CompletableFuture<R>() {
@Override public boolean cancel(boolean mayInterruptIfRunning) {
if (mayInterruptIfRunning) {
......@@ -119,7 +119,8 @@ public final class Java8CallAdapterFactory extends CallAdapter.Factory {
}
}
private static class ResponseCallAdapter implements CallAdapter<CompletableFuture<?>> {
private static final class ResponseCallAdapter<R>
implements CallAdapter<R, CompletableFuture<Response<R>>> {
private final Type responseType;
ResponseCallAdapter(Type responseType) {
......@@ -130,7 +131,7 @@ public final class Java8CallAdapterFactory extends CallAdapter.Factory {
return responseType;
}
@Override public <R> CompletableFuture<Response<R>> adapt(final Call<R> call) {
@Override public CompletableFuture<Response<R>> adapt(final Call<R> call) {
final CompletableFuture<Response<R>> future = new CompletableFuture<Response<R>>() {
@Override public boolean cancel(boolean mayInterruptIfRunning) {
if (mayInterruptIfRunning) {
......
......@@ -72,7 +72,7 @@ public final class Java8CallAdapterFactoryTest {
}
@Test public void nonListenableFutureReturnsNull() {
CallAdapter<?> adapter = factory.get(String.class, NO_ANNOTATIONS, retrofit);
CallAdapter<?, ?> adapter = factory.get(String.class, NO_ANNOTATIONS, retrofit);
assertThat(adapter).isNull();
}
......
......@@ -23,7 +23,7 @@ import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Scheduler;
final class RxJavaCallAdapter implements CallAdapter<Object> {
final class RxJavaCallAdapter<R> implements CallAdapter<R, Object> {
private final Type responseType;
private final Scheduler scheduler;
private final boolean isResult;
......@@ -45,7 +45,7 @@ final class RxJavaCallAdapter implements CallAdapter<Object> {
return responseType;
}
@Override public <R> Object adapt(Call<R> call) {
@Override public Object adapt(Call<R> call) {
OnSubscribe<Response<R>> callFunc = new CallOnSubscribe<>(call);
OnSubscribe<?> func;
......
......@@ -80,7 +80,7 @@ public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
}
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
String canonicalName = rawType.getCanonicalName();
boolean isSingle = "rx.Single".equals(canonicalName);
......
......@@ -54,7 +54,7 @@ public final class RxJavaCallAdapterFactoryTest {
}
@Test public void nonRxJavaTypeReturnsNull() {
CallAdapter<?> adapter = factory.get(String.class, NO_ANNOTATIONS, retrofit);
CallAdapter<?, ?> adapter = factory.get(String.class, NO_ANNOTATIONS, retrofit);
assertThat(adapter).isNull();
}
......
......@@ -50,8 +50,8 @@ public final class ScalarsConverterPrimitivesFactoryTest {
static class DirectCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new CallAdapter<Object>() {
public CallAdapter<?, ?> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new CallAdapter<Object, Object>() {
@Override public Type responseType() {
return returnType;
}
......
......@@ -51,15 +51,16 @@ public final class BehaviorDelegate<T> {
}
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public T returning(Call<?> call) {
final Call<?> behaviorCall = new BehaviorCall<>(behavior, executor, call);
public <R> T returning(Call<R> call) {
final Call<R> behaviorCall = new BehaviorCall<>(behavior, executor, call);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[] { service },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
public T invoke(Object proxy, Method method, Object[] args) throws Throwable {
Type returnType = method.getGenericReturnType();
Annotation[] methodAnnotations = method.getAnnotations();
CallAdapter<?> callAdapter = retrofit.callAdapter(returnType, methodAnnotations);
CallAdapter<R, T> callAdapter =
(CallAdapter<R, T>) retrofit.callAdapter(returnType, methodAnnotations);
return callAdapter.adapt(behaviorCall);
}
});
......
......@@ -20,11 +20,12 @@ import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Adapts a {@link Call} into the type of {@code T}. Instances are created by {@linkplain Factory a
* factory} which is {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into
* the {@link Retrofit} instance.
* Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are
* created by {@linkplain Factory a factory} which is
* {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into the {@link Retrofit}
* instance.
*/
public interface CallAdapter<T> {
public interface CallAdapter<R, T> {
/**
* Returns the value type that this adapter uses when converting the HTTP response body to a Java
* object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
......@@ -52,7 +53,7 @@ public interface CallAdapter<T> {
* }
* </code></pre>
*/
<R> T adapt(Call<R> call);
T adapt(Call<R> call);
/**
* Creates {@link CallAdapter} instances based on the return type of {@linkplain
......@@ -63,7 +64,7 @@ public interface CallAdapter<T> {
* Returns a call adapter for interface methods that return {@code returnType}, or null if it
* cannot be handled by this factory.
*/
public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
/**
......
......@@ -27,18 +27,18 @@ final class DefaultCallAdapterFactory extends CallAdapter.Factory {
static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public <R> Call<R> adapt(Call<R> call) {
@Override public Call<Object> adapt(Call<Object> call) {
return call;
}
};
......
......@@ -29,17 +29,17 @@ final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
}
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public <R> Call<R> adapt(Call<R> call) {
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
......
......@@ -25,7 +25,7 @@ import okio.ForwardingSource;
import okio.Okio;
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T> serviceMethod;
private final ServiceMethod<T, ?> serviceMethod;
private final Object[] args;
private volatile boolean canceled;
......@@ -35,7 +35,7 @@ final class OkHttpCall<T> implements Call<T> {
private Throwable creationFailure; // Either a RuntimeException or IOException.
private boolean executed;
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
......
......@@ -21,9 +21,9 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
......@@ -57,7 +57,7 @@ import static retrofit2.Utils.checkNotNull;
* @author Jake Wharton (jw@squareup.com)
*/
public final class Retrofit {
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
private final okhttp3.Call.Factory callFactory;
private final HttpUrl baseUrl;
......@@ -142,8 +142,9 @@ public final class Retrofit {
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
......@@ -158,12 +159,14 @@ public final class Retrofit {
}
}
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
......@@ -197,7 +200,7 @@ public final class Retrofit {
*
* @throws IllegalArgumentException if no call adapter available for {@code type}.
*/
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
......@@ -207,14 +210,14 @@ public final class Retrofit {
*
* @throws IllegalArgumentException if no call adapter available for {@code type}.
*/
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
......
......@@ -56,17 +56,17 @@ import retrofit2.http.QueryMap;
import retrofit2.http.Url;
/** Adapts an invocation of an interface method into an HTTP call. */
final class ServiceMethod<T> {
final class ServiceMethod<R, T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
final okhttp3.Call.Factory callFactory;
final CallAdapter<?> callAdapter;
final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, T> responseConverter;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
......@@ -76,7 +76,7 @@ final class ServiceMethod<T> {
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
ServiceMethod(Builder<T> builder) {
ServiceMethod(Builder<R, T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
......@@ -113,7 +113,7 @@ final class ServiceMethod<T> {
}
/** Builds a method return value from an HTTP response body. */
T toResponse(ResponseBody body) throws IOException {
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
......@@ -122,7 +122,7 @@ final class ServiceMethod<T> {
* requires potentially-expensive reflection so it is best to build each service method only once
* and reuse it. Builders cannot be reused.
*/
static final class Builder<T> {
static final class Builder<T, R> {
final Retrofit retrofit;
final Method method;
final Annotation[] methodAnnotations;
......@@ -146,7 +146,7 @@ final class ServiceMethod<T> {
Set<String> relativeUrlParamNames;
ParameterHandler<?>[] parameterHandlers;
Converter<ResponseBody, T> responseConverter;
CallAdapter<?> callAdapter;
CallAdapter<T, R> callAdapter;
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
......@@ -218,7 +218,7 @@ final class ServiceMethod<T> {
return new ServiceMethod<>(this);
}
private CallAdapter<?> createCallAdapter() {
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
......@@ -229,7 +229,8 @@ final class ServiceMethod<T> {
}
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.callAdapter(returnType, annotations);
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
......
......@@ -70,10 +70,10 @@ public final class ExecutorCallAdapterFactoryTest {
@Test public void adaptedCallExecute() throws IOException {
Type returnType = new TypeToken<Call<String>>() {}.getType();
CallAdapter<Call<?>> adapter =
(CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
CallAdapter<String, Call<String>> adapter =
(CallAdapter<String, Call<String>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
final Response<String> response = Response.success("Hi");
Call<String> call = (Call<String>) adapter.adapt(new EmptyCall() {
Call<String> call = adapter.adapt(new EmptyCall() {
@Override public Response<String> execute() throws IOException {
return response;
}
......@@ -83,15 +83,15 @@ public final class ExecutorCallAdapterFactoryTest {
@Test public void adaptedCallEnqueueUsesExecutorForSuccessCallback() {
Type returnType = new TypeToken<Call<String>>() {}.getType();
CallAdapter<Call<?>> adapter =
(CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
CallAdapter<String, Call<String>> adapter =
(CallAdapter<String, Call<String>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
final Response<String> response = Response.success("Hi");
EmptyCall originalCall = new EmptyCall() {
@Override public void enqueue(Callback<String> callback) {
callback.onResponse(this, response);
}
};
Call<String> call = (Call<String>) adapter.adapt(originalCall);
Call<String> call = adapter.adapt(originalCall);
call.enqueue(callback);
verify(callbackExecutor).execute(any(Runnable.class));
verify(callback).onResponse(call, response);
......@@ -99,15 +99,15 @@ public final class ExecutorCallAdapterFactoryTest {
@Test public void adaptedCallEnqueueUsesExecutorForFailureCallback() {
Type returnType = new TypeToken<Call<String>>() {}.getType();
CallAdapter<Call<?>> adapter =
(CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
CallAdapter<String, Call<String>> adapter =
(CallAdapter<String, Call<String>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
final Throwable throwable = new IOException();
EmptyCall originalCall = new EmptyCall() {
@Override public void enqueue(Callback<String> callback) {
callback.onFailure(this, throwable);
}
};
Call<String> call = (Call<String>) adapter.adapt(originalCall);
Call<String> call = adapter.adapt(originalCall);
call.enqueue(callback);
verify(callbackExecutor).execute(any(Runnable.class));
verifyNoMoreInteractions(callbackExecutor);
......@@ -117,10 +117,10 @@ public final class ExecutorCallAdapterFactoryTest {
@Test public void adaptedCallCloneDeepCopy() {
Type returnType = new TypeToken<Call<String>>() {}.getType();
CallAdapter<Call<?>> adapter =
(CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
CallAdapter<String, Call<String>> adapter =
(CallAdapter<String, Call<String>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
Call<String> delegate = mock(Call.class);
Call<String> call = (Call<String>) adapter.adapt(delegate);
Call<String> call = adapter.adapt(delegate);
Call<String> cloned = call.clone();
assertThat(cloned).isNotSameAs(call);
verify(delegate).clone();
......@@ -129,10 +129,10 @@ public final class ExecutorCallAdapterFactoryTest {
@Test public void adaptedCallCancel() {
Type returnType = new TypeToken<Call<String>>() {}.getType();
CallAdapter<Call<?>> adapter =
(CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
CallAdapter<String, Call<String>> adapter =
(CallAdapter<String, Call<String>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
Call<String> delegate = mock(Call.class);
Call<String> call = (Call<String>) adapter.adapt(delegate);
Call<String> call = adapter.adapt(delegate);
call.cancel();
verify(delegate).cancel();
verifyNoMoreInteractions(delegate);
......
......@@ -2501,7 +2501,7 @@ public final class RequestBuilderTest {
}
}
static Request buildRequest(Class<?> cls, Object... args) {
static <T> Request buildRequest(Class<T> cls, Object... args) {
final AtomicReference<Request> requestRef = new AtomicReference<>();
okhttp3.Call.Factory callFactory = new okhttp3.Call.Factory() {
@Override public okhttp3.Call newCall(Request request) {
......@@ -2517,9 +2517,11 @@ public final class RequestBuilderTest {
.build();
Method method = TestingUtils.onlyMethod(cls);
ServiceMethod<?> serviceMethod = retrofit.loadServiceMethod(method);
OkHttpCall<?> okHttpCall = new OkHttpCall<>(serviceMethod, args);
Call<?> call = (Call<?>) serviceMethod.callAdapter.adapt(okHttpCall);
//noinspection unchecked
ServiceMethod<T, Call<T>> serviceMethod =
(ServiceMethod<T, Call<T>>) retrofit.loadServiceMethod(method);
Call<T> okHttpCall = new OkHttpCall<>(serviceMethod, args);
Call<T> call = serviceMethod.callAdapter.adapt(okHttpCall);
try {
call.execute();
throw new AssertionError();
......
......@@ -231,18 +231,18 @@ public final class RetrofitTest {
final AtomicBoolean factoryCalled = new AtomicBoolean();
final AtomicBoolean adapterCalled = new AtomicBoolean();
class MyCallAdapterFactory extends CallAdapter.Factory {
@Override public CallAdapter<?> get(final Type returnType, Annotation[] annotations,
@Override public CallAdapter<?, ?> get(final Type returnType, Annotation[] annotations,
Retrofit retrofit) {
factoryCalled.set(true);
if (getRawType(returnType) != Call.class) {
return null;
}
return new CallAdapter<Call<?>>() {
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return getParameterUpperBound(0, (ParameterizedType) returnType);
}
@Override public <R> Call<R> adapt(Call<R> call) {
@Override public Call<Object> adapt(Call<Object> call) {
adapterCalled.set(true);
return call;
}
......@@ -262,17 +262,17 @@ public final class RetrofitTest {
@Test public void customCallAdapter() {
class GreetingCallAdapterFactory extends CallAdapter.Factory {
@Override public CallAdapter<String> get(Type returnType, Annotation[] annotations,
@Override public CallAdapter<Object, String> get(Type returnType, Annotation[] annotations,
Retrofit retrofit) {
if (getRawType(returnType) != String.class) {
return null;
}
return new CallAdapter<String>() {
return new CallAdapter<Object, String>() {
@Override public Type responseType() {
return String.class;
}
@Override public <R> String adapt(Call<R> call) {
@Override public String adapt(Call<Object> call) {
return "Hi!";
}
};
......@@ -291,7 +291,7 @@ public final class RetrofitTest {
@Test public void methodAnnotationsPassedToCallAdapter() {
final AtomicReference<Annotation[]> annotationsRef = new AtomicReference<>();
class MyCallAdapterFactory extends CallAdapter.Factory {
@Override public CallAdapter<?> get(Type returnType, Annotation[] annotations,
@Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit) {
annotationsRef.set(annotations);
return null;
......@@ -1022,7 +1022,7 @@ public final class RetrofitTest {
Type type = String.class;
Annotation[] annotations = new Annotation[0];
CallAdapter<?> expectedAdapter = mock(CallAdapter.class);
CallAdapter<?, ?> expectedAdapter = mock(CallAdapter.class);
CallAdapter.Factory factory = mock(CallAdapter.Factory.class);
Retrofit retrofit = new Retrofit.Builder()
......@@ -1032,7 +1032,7 @@ public final class RetrofitTest {
doReturn(expectedAdapter).when(factory).get(type, annotations, retrofit);
CallAdapter<?> actualAdapter = retrofit.callAdapter(type, annotations);
CallAdapter<?, ?> actualAdapter = retrofit.callAdapter(type, annotations);
assertThat(actualAdapter).isSameAs(expectedAdapter);
verify(factory).get(type, annotations, retrofit);
......@@ -1043,11 +1043,11 @@ public final class RetrofitTest {
Type type = String.class;
Annotation[] annotations = new Annotation[0];
CallAdapter<?> expectedAdapter = mock(CallAdapter.class);
CallAdapter<?, ?> expectedAdapter = mock(CallAdapter.class);
CallAdapter.Factory factory2 = mock(CallAdapter.Factory.class);
CallAdapter.Factory factory1 = spy(new CallAdapter.Factory() {
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return retrofit.nextCallAdapter(this, returnType, annotations);
}
});
......@@ -1060,7 +1060,7 @@ public final class RetrofitTest {
doReturn(expectedAdapter).when(factory2).get(type, annotations, retrofit);
CallAdapter<?> actualAdapter = retrofit.callAdapter(type, annotations);
CallAdapter<?, ?> actualAdapter = retrofit.callAdapter(type, annotations);
assertThat(actualAdapter).isSameAs(expectedAdapter);
verify(factory1).get(type, annotations, retrofit);
......@@ -1073,17 +1073,17 @@ public final class RetrofitTest {
Type type = String.class;
Annotation[] annotations = new Annotation[0];
CallAdapter<?> expectedAdapter = mock(CallAdapter.class);
CallAdapter<?, ?> expectedAdapter = mock(CallAdapter.class);
CallAdapter.Factory factory3 = mock(CallAdapter.Factory.class);
CallAdapter.Factory factory2 = spy(new CallAdapter.Factory() {
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return retrofit.nextCallAdapter(this, returnType, annotations);
}
});
CallAdapter.Factory factory1 = spy(new CallAdapter.Factory() {
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return retrofit.nextCallAdapter(this, returnType, annotations);
}
});
......@@ -1097,7 +1097,7 @@ public final class RetrofitTest {
doReturn(expectedAdapter).when(factory3).get(type, annotations, retrofit);
CallAdapter<?> actualAdapter = retrofit.callAdapter(type, annotations);
CallAdapter<?, ?> actualAdapter = retrofit.callAdapter(type, annotations);
assertThat(actualAdapter).isSameAs(expectedAdapter);
verify(factory1).get(type, annotations, retrofit);
......
......@@ -24,7 +24,7 @@ public final class DelegatingCallAdapterFactory extends CallAdapter.Factory {
public boolean called;
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
called = true;
return retrofit.nextCallAdapter(this, returnType, annotations);
}
......
......@@ -24,7 +24,7 @@ public final class NonMatchingCallAdapterFactory extends CallAdapter.Factory {
public boolean called;
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
called = true;
return null;
}
......
......@@ -32,7 +32,7 @@ import retrofit2.http.GET;
* A sample showing a custom {@link CallAdapter} which adapts the built-in {@link Call} to a custom
* version whose callback has more granular methods.
*/
public final class ErrorHandlingCallAdapter {
public final class ErrorHandlingAdapter {
/** A callback which offers granular callbacks for various conditions. */
interface MyCallback<T> {
/** Called for [200, 300) responses. */
......@@ -59,7 +59,7 @@ public final class ErrorHandlingCallAdapter {
}
public static class ErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
@Override public CallAdapter<MyCall<?>> get(Type returnType, Annotation[] annotations,
@Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit) {
if (getRawType(returnType) != MyCall.class) {
return null;
......@@ -68,17 +68,27 @@ public final class ErrorHandlingCallAdapter {
throw new IllegalStateException(
"MyCall must have generic type (e.g., MyCall<ResponseBody>)");
}
final Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor callbackExecutor = retrofit.callbackExecutor();
return new CallAdapter<MyCall<?>>() {
@Override public Type responseType() {
return responseType;
}
Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
Executor callbackExecutor = retrofit.callbackExecutor();
return new ErrorHandlingCallAdapter<>(responseType, callbackExecutor);
}
@Override public <R> MyCall<R> adapt(Call<R> call) {
return new MyCallAdapter<>(call, callbackExecutor);
}
};
private static final class ErrorHandlingCallAdapter<R> implements CallAdapter<R, MyCall<R>> {
private final Type responseType;
private final Executor callbackExecutor;
ErrorHandlingCallAdapter(Type responseType, Executor callbackExecutor) {
this.responseType = responseType;
this.callbackExecutor = callbackExecutor;
}
@Override public Type responseType() {
return responseType;
}
@Override public MyCall<R> adapt(Call<R> call) {
return new MyCallAdapter<>(call, callbackExecutor);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册