2016-07-05 75 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不支持該功能:(