【问题标题】:Android using Retrofit with generic typeAndroid 使用具有泛型类型的 Retrofit
【发布时间】:2016-11-24 15:18:24
【问题描述】:

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

例如这样的:

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

我读过Retrofit在运行时使用方法签名来确定返回类型,在那种情况下甚至可以有像上面这样的通用接口吗?

【问题讨论】:

    标签: java android generics retrofit retrofit2


    【解决方案1】:

    是的,我认为这是可能的,但要小心改造返回一些Call 所以你可以使用Call&lt;T&gt; 类似的方法创建一个接口,除了

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

    【讨论】:

      【解决方案2】:

      我能想到的传递该信息的唯一方法是引入一个包装器来保存值及其类型(或类型标记以简化 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(反)序列化策略。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 2020-08-26
        • 2015-07-09
        • 2020-03-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多