Java Android使用泛型类型的改型

Java Android使用泛型类型的改型,java,android,generics,retrofit,retrofit2,Java,Android,Generics,Retrofit,Retrofit2,是否有可能以使用泛型的方式进行改装 例如,类似这样的事情: public interface RetroInterface<T> { @GET("content/{id}") T getById(@Path("id") int id); } 公共接口{ @获取(“content/{id}”) T getById(@Path(“id”)int-id); } 我已经读到,改型在运行时使用方法签名来确定返回类型,在这种情况下,是否有可能使用上述通用接口?是的,我认为这是

是否有可能以使用泛型的方式进行改装

例如,类似这样的事情:

public interface RetroInterface<T> {
    @GET("content/{id}")
    T getById(@Path("id") int id);
}
公共接口{
@获取(“content/{id}”)
T getById(@Path(“id”)int-id);
}

我已经读到,改型在运行时使用方法签名来确定返回类型,在这种情况下,是否有可能使用上述通用接口?

是的,我认为这是可能的,但请小心改型返回一些
调用
,这样您就可以创建一个与
调用
类似的方法的接口,除了


但是您真的需要为服务创建模板吗?因为在获取注释的过程中,您要求服务器提供一个特定的ressource,这样您就知道了响应的类型,所以传递该信息的唯一方法是引入一个包装器来保存值及其类型(或者使用类型令牌来简化Gson)

final类泛型体{
最终T体;
最终类型令牌类型令牌;
GenericBody(最终T正文、最终TypeToken TypeToken){
这个身体=身体;
this.typeToken=typeToken;
}
}
然后,可以按如下方式声明示例服务:

interface IGenericService {

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

}
接口IGenericService{
@职位(“/”)
呼叫公告(@Body@SuppressWarnings(“rawtypes”)GenericBody GenericBody);
}
在这里,调用被声明为不返回任何内容,genericBody被故意设置为原始类型,以使其通过改造验证

接下来是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;
}

}
final类GenericBodyTypeAdapterFactory
实现TypeAdapterFactory{
私有静态最终TypeAdapterFactory genericBodyTypeAdapterFactory=新genericBodyTypeAdapterFactory();
私有GenericBodyTypeAdapterFactory(){
}
静态TypeAdapterFactory getGenericBodyTypeAdapterFactory(){
返回genericBodyTypeAdapterFactory;
}
@凌驾
公共类型适配器创建(最终Gson Gson、最终TypeToken TypeToken){
如果(!GenericBody.class.isAssignableFrom(typeToken.getRawType())){
返回null;
}
最终类型适配器genericBodyTypeAdapter=新类型适配器(){
@凌驾
公共无效写入(最终JsonWriter out,最终GenericBody值)
抛出IOException{
最终T body=value.body;
final-TypeAdapter-TypeAdapter=gson.getDelegateAdapter(GenericBodyTypeAdapterFactory.this,value.typeToken);
类型适配器。写入(输出,正文);
}
@凌驾
公共通用主体已读(中的最终JsonReader){
抛出新的UnsupportedOperationException();
}
};
@抑制警告(“未选中”)
final TypeAdapter TypeAdapter=(TypeAdapter)genericBodyTypeAdapter;
返回类型适配器;
}
}
它的作用是:

检查是否可以处理GenericBody实例; 通过绑定的类型令牌解析相应的类型适配器; 将泛型主体值写入输出。 不执行读取

使用示例(全部模拟(staticResponse(applicationJsonMediaType,“OK”))可以轻松转换为代码):

私有静态最终类型令牌stringListTypeToken=新建
TypeToken(){
};
私有静态最终Gson Gson=new GsonBuilder()
.registerTypeAdapterFactory(getGenericBodyTypeAdapterFactory())
.create();
私有静态最终OkHttpClient客户端=新的OkHttpClient.Builder()
.addInterceptor(静态响应(applicationJsonMediaType,“OK”))
.build();
私人静态最终改装改装=新改装.Builder()
.baseUrl(“http://whatever")
.客户(客户)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
专用静态最终IGenericService genericService=
create(IGenericService.class);
公共静态void main(最终字符串…参数)
抛出IOException{
最终通用主体=新通用主体(asList(“foo”、“bar”、“baz”),
stringListTypeToken);
genericService.post(body.execute();
}
这将根据正确配置的Gson(反)序列化策略将[“foo”、“bar”、“baz”]写入输出流

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

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