Android使用Retrofit与泛型类型

时间:2016-07-21 07:09:46

标签: java android generics retrofit retrofit2

是否可以以使用泛型类型的方式使用改造?

例如:

public interface RetroInterface<T> {
    @GET("content/{id}")
    T getById(@Path("id") int id);
}

我已经读过Retrofit使用方法签名来确定运行时的返回类型,在这种情况下,是否可以使用如上所述的通用接口?

2 个答案:

答案 0 :(得分:0)

是的,我认为这是可能的,但要小心改造返回一些Call所以你可以用Call<T>方法创建一个界面,除了

但您真的需要为服务创建模板吗?因为在你得到注释时你要求服务器一个特定的资源,所以你知道响应的类型

答案 1 :(得分:0)

传递信息的唯一方法是引入一个包装器,以容纳值及其类型(或类型令牌以简化Gson)。

final class GenericBody<T> {

final T body;
final TypeToken<T> typeToken;

GenericBody(final T body, final TypeToken<T> typeToken) {
    this.body = body;
    this.typeToken = typeToken;
}

}

然后可以将示例服务声明如下:

interface IGenericService {

@POST("/")
Call<Void> post(@Body @SuppressWarnings("rawtypes") GenericBody genericBody);

}

在这里,该Call被声明为不返回任何内容,并且有意将genericBody设为原始类型,以使其通过Retrofit验证。

接下来,是Gson部分。

final class GenericBodyTypeAdapterFactory
    implements TypeAdapterFactory {

private static final TypeAdapterFactory genericBodyTypeAdapterFactory = new GenericBodyTypeAdapterFactory();

private GenericBodyTypeAdapterFactory() {
}

static TypeAdapterFactory getGenericBodyTypeAdapterFactory() {
    return genericBodyTypeAdapterFactory;
}

@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
    if ( !GenericBody.class.isAssignableFrom(typeToken.getRawType()) ) {
        return null;
    }
    final TypeAdapter<GenericBody<T>> genericBodyTypeAdapter = new TypeAdapter<GenericBody<T>>() {
        @Override
        public void write(final JsonWriter out, final GenericBody<T> value)
                throws IOException {
            final T body = value.body;
            final TypeAdapter<T> typeAdapter = gson.getDelegateAdapter(GenericBodyTypeAdapterFactory.this, value.typeToken);
            typeAdapter.write(out, body);
        }

        @Override
        public GenericBody<T> read(final JsonReader in) {
            throw new UnsupportedOperationException();
        }
    };
    @SuppressWarnings("unchecked")
    final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) genericBodyTypeAdapter;
    return typeAdapter;
}

}

它是什么:

检查它是否可以处理GenericBody实例; 通过绑定类型标记为解析适当的类型适配器; 将通用主体值写入输出。 没有读取。

使用示例(可轻松转换为代码的完整模拟(staticResponse(applicationJsonMediaType,“ OK”))):

private static final TypeToken<List<String>> stringListTypeToken = new 
TypeToken<List<String>>() {
};

 private static final Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(getGenericBodyTypeAdapterFactory())
    .create();

private static final OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(staticResponse(applicationJsonMediaType, "OK"))
    .build();

 private static final Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://whatever")
    .client(client)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build();

 private static final IGenericService genericService = 
 retrofit.create(IGenericService.class);

 public static void main(final String... args)
    throws IOException {
final GenericBody<List<String>> body = new GenericBody<>(asList("foo", "bar", "baz"), 
stringListTypeToken);
genericService.post(body).execute();
}

这会将[“ foo”,“ bar”,“ baz”]写入输出流,并遵循正确配置的Gson(反)序列化策略。