当前位置: 首页 > 面试题库 >

带有Retrofit 2的多个转换器

长孙绍辉
2023-03-14
问题内容

我有HATEOAS(HAL)
REST服务,并设法通过下面的代码与之交谈(使用怪异的转换引擎),但是当我尝试合并转换器(stallonestallone2)时,应用程序将始终选择第一个转换器,而不是当然,这会导致错误。

如何避免重复的改造,只是在小字体细节上有所不同?

public interface Stallone {
   @GET("/discovery")
   Call<DiscoveryResponse> discover();
   @POST()
   Call<LoginResponse> login(@Url String url, @Body LoginRequest secret);
}



   public static void main(String... args) throws IOException {
      // Initialize a converter for each supported (return) type
      final Stallone stallone = new Retrofit.Builder()
         .baseUrl(BASE)
         .addConverterFactory(HALConverterFactory.create(DiscoveryResponse.class))
         .build().create(Stallone.class);
      final Stallone stallone2 = new Retrofit.Builder()
         .baseUrl(BASE)
         .addConverterFactory(HALConverterFactory.create(LoginResponse.class))
         .build().create(Stallone.class);

      // Follow the HAL links
      Response<DiscoveryResponse> response = stallone.discover().execute();
      System.out.println(response.code() + " " + response.message());
      Assert.assertNotNull(response.body());
      String loginPath = response.body().getLogin();
      Assert.assertEquals(loginPath, "/login");

      // Follow another link
      if (loginPath.startsWith("/"))
         loginPath = loginPath.substring(1);
      Response<LoginResponse> response2 =
         stallone2.login(loginPath,
                        new LoginRequest(AUTH0TOKEN, null)).execute();
      System.out.println(response2.code() + " " + response2.message());
      Assert.assertNotNull(response2.body());

      String setupPath = response2.body().getSetup();
      Assert.assertEquals(setupPath, "/setup");

      System.out.println("All OK!");
   }



public final class HALConverterFactory extends Converter.Factory {

   private final Gson gson;

   public static HALConverterFactory create(Class<?> type) {
      return new HALConverterFactory(type);
   }

   private HALConverterFactory(Class<?> type) {
      if (!HalResource.class.isAssignableFrom(type))
         throw new NullPointerException("Type should be a subclass of HalResource");
      GsonBuilder builder = new GsonBuilder();
      builder.registerTypeAdapter(HalResource.class, new HalSerializer());
      builder.registerTypeAdapter(HalResource.class, new HalDeserializer(type));
      builder.setExclusionStrategies(new HalExclusionStrategy());
      this.gson = builder.create();
   }

   @Override
   public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
      return new HALResponseBodyConverter<>(gson);
   }

   @Override public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {
      return new GsonRequestBodyConverter<>(gson, type);
   }
}



final class HALResponseBodyConverter<T extends HalResource>
   implements Converter<ResponseBody, T> {
   private final Gson gson;

   HALResponseBodyConverter(Gson gson) {
      this.gson = gson;
   }

   @Override public T convert(ResponseBody value) throws IOException {
      BufferedSource source = value.source();
      try {
         String s = source.readString(Charset.forName("UTF-8"));
         return (T) gson.fromJson(s, HalResource.class);
      } catch (Exception e) {
         throw new RuntimeException(e);
      } finally {
         closeQuietly(source);
      }
   }

   private static void closeQuietly(Closeable closeable) {
      if (closeable == null) return;
      try {
         closeable.close();
      } catch (IOException ignored) {
      }
   }
}

同样,问题是 当您尝试像这样缩短上述时间时:

  final Stallone stallone = new Retrofit.Builder()
     .baseUrl(BASE)
.addConverterFactory(HALConverterFactory.create(DiscoveryResponse.class))
     .addConverterFactory(HALConverterFactory.create(LoginResponse.class))
     .build().create(Stallone.class);

您会在该Response<LoginResponse> response2 = ...行得到一个例外:

线程“主”中的异常java.lang.ClassCastException:com.example.retrofit.DiscoveryResponse无法转换为com.example.retrofit.LoginResponse


问题答案:

如果类型不匹配nullConverter.Factory则需要从中返回。将Class<?>周围保持在一个字段中进行比较。

@Override
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
  if (!this.type.equals(type)) {
    return null;
  }
  return new HALResponseBodyConverter<>(gson);
}

这将允许使用多个实例,因为每个实例仅适用于其自己的类型。

就是说,但是,您可能仅使用单个转换器并从Type传入的类中拉取类就可以摆脱现实。

@Override
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
  if (!HALResponse.class.isAssignableFrom(type)) {
    return null;
  }
  // TODO create converter with `type` now that you know what it is...
}

您可以查看回购中的Wire转换器,这是一个完整的示例



 类似资料:
  • 我正在将改型2与Gson和RxJava结合使用。我的JSON数据如下所示: 在上面的示例中,“键”1、2、3是整数,但也可以是唯一的字符串。我想将这个JSON数据映射到如下内容: 将动态键(1、2、3)放入对象的最佳方式是什么?我自己没有托管JSON数据,因此无法将其更改为其他格式。

  • 我对我的可视寻呼机有一个自定义要求。我想要的是我的寻呼机应该有一个类似DepthPageTransformer的默认水平pageTransformer。现在,在屏幕上我有一个按钮,我希望我的当前页面从底部滑动到顶部,我的下一个页面像VerticalPageTransformer一样替换它,一旦页面改变,页面转换器应该改变回默认的DepthPageTransformer。 所以基本上我想在运行时应用

  • 问题内容: 我需要构建一个具有多个窗口的应用程序。在其中一个窗口中,我需要能够玩一个简单的游戏,而另一个窗口必须显示问题并获得影响游戏的用户的响应。 (1)我想使用pygame来制作游戏。有一种 简单的 方法可以让pygame在多个窗口中运行吗? (2)如果没有简单的方法可以解决(1),是否有一种简单的方法来使用其他一些Python GUI结构,从而允许我同时运行pygame和另一个窗口? 问题答

  • 问题内容: 我正在尝试建立一个查询,该查询将找到所有用户文档(docType =用户),然后根据许多过滤器对其进行过滤。例如位置,性别,年龄等。过滤器是根据我正在构建的搜索功能上的用户输入来添加/删除的。 以下没有结果: 以下返回结果: 后者虽然返回结果,但从长远来看是行不通的,因为我可能想为年龄,性别等添加一个额外的过滤器,而且我似乎无法添加多个字段。如果我删除位置过滤器,则第一个查询有效。 问

  • 问题内容: 我有一个xsl文件,在这里我需要使用来自外部源的参数。我正在使用Java,我的代码如下所示: 但是,第二行引发异常- 变量或参数’variable_name’未定义。 我意识到XSL已编译,并且可能在创建转换器时已编译。 那么,如何将参数传递给转换?应该如何使用setParameter方法? 问题答案: 如果传递如下参数: 可以通过转换获取参数: