2016-07-05 120 views
2

虽然使用retrofitGson我遇到提供的类型和最终类型不同但需要相同类型参数的情况。如何在类型之间传递类型参数?

我们在服务这个方法:

@GET("awesome") 
AwesomeCall<AwesomeObject> get(); 

而且我想AwesomeCall返回一个AwesomeResult其中包含相关AwesomeObject或错误(铭记这“真棒” API忽略HTTP,总是返回200,只给一个错误的对象,而不是我们预期的AwesomeObject

我要的是改装解析AwesomeResultAwesomeCall回这样的对象,如果没有与请求没有问题。

我遇到的问题是改造只为我提供服务的返回类型,但我需要获取不同的对象。

PS:这样做是为了使该服务没有任何引用可能会泄漏到代码中更高级别的改造对象。

回答

3

因此,在深入了解反思的深度之后,我发现您可以实现ParameterizedType(因为它是一个接口)并使用它来生成来自改造的不同调用。

里面我CallAdapter.Factory实现我创造了这个类型:

private static class AwesomeResponseType implements ParameterizedType { 
    private final Type innerType; 

    public BrainResponseType(Type innerType) { 
     this.innerType = innerType; 
    } 

    @Override 
    public Type[] getActualTypeArguments() { 
     return new Type[] {innerType}; 
    } 

    @Override 
    public Type getRawType() { 
     return AwesomeResponse.class; 
    } 

    @Override 
    public Type getOwnerType() { 
     return null; 
    } 
} 

和创建适配器时我注入内部类型是这样的:

final Type innerType = getParameterUpperBound(0, (ParameterizedType) returnType); 
ParameterizedType parameterizedType = new AwesomeResponseType(innerType); 

和使用的parameterizedType创建自定义CallAdapter像此:

private static class AwesomeCallAdapter<T> implements CallAdapter<AwesomeCall<?>> { 

    private final Type responseType; 

    private AwesomeCallAdapter(Type responseType) { 
     this.responseType = responseType; 
    } 

    @Override 
    public Type responseType() { 
     return responseType; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public <R> AwesomeCall<T> adapt(Call<R> call) { 
     return new AwesomeCall<>((Call<AwesomeResponse<T>>)call); 
    } 

} 

The AwesomeCall现在可以高兴地处理该预期的AwesomeResponse一个电话:

public class AwesomeCall<T> { 
    private final Call<AwesomeResponse<T>> call; 

    public AwesomeCall(Call<AwesomeResponse<T>> call) { 
     this.call = call; 
    } 

    public AwesomeResponse<T> execute() throws IOException { 
     Response<BrainResponse<T>> response = call.execute(); 
     return response.isSuccessful() ? response.body() : errorResponseFrom(response); 
    } 

    private AwesomeResponse<T> errorResponseFrom(Response<AwesomeResponse<T>> response) { 
     return new AwesomeResponse<>(null, new AwesomeError(response.message())); 
    } 

} 

如果使用的是番石榴,我相信你没有实现ParameterizedTypeTypeToken有一个API来做到这一点:

TypeToken.of(AwesomeResponse.class).where(new TypeParameter<T>() {}, innerType).getType(); 

但可悲的是,在GSON的TypeToken不支持该功能:(

相关问题