【问题标题】:Retrofit Dynamic ResponseBody改造动态响应体
【发布时间】:2016-07-28 08:12:27
【问题描述】:

我计划使用 Retrofit 制作一个通用服务类,

@GET
Call<ResponseBody> makeGetRequest(@Url String url);

@POST
Call<ResponseBody> makePostRequest(@Url String url, @Body RequestBody parameters);

在这段代码中,我需要将 (ResponseBody) 作为动态 JSON POJO 类名传递,例如 LoginRes

举个例子,

Call<LoginRes> // But this class will be dynamic

我会通过 ResponseBody 但那个 ResponseBody 不知道我想要哪个类。

为什么我想要这个,因为在结果之后

gson.fromJson(response, LoginRes.class);

所以,在得到 Retrofit 的结果后,我们需要再次转换为 gson.fromJson。

所以我想将动态响应作为 Retrofit 传递,以便它根据我的 pojo 类进行响应,

我知道当我通过 LoginRes 而不是 ResponseBody 时这工作正常,因为正如我已经告诉 Response 我们需要在 LoginRes 中的响应。

如果我通过了

Call<LoginRes> // if i pass this way its working fine no need to convert my response i can access my all properties from that LoginRes class directly. 

这是我调用 Web 服务的示例。

Call<ResponseBody> call = apiService.makePostRequest("/Buyer/LoginApp", requestBody);

这就是我调用服务的方式。

如果我对我的问题的解释不清楚,请告诉我。

等待一些好的回应和建议。

谢谢 马达夫

【问题讨论】:

  • 那么您想要拥有可以将 JSON 响应转换为各种可能完全不相关的类的相同功能吗?
  • 实际上,如果我可以通过 ResponseBody 动态或其他方式传递.. 我需要关于此的建议。

标签: java android android-studio retrofit retrofit2


【解决方案1】:

这有点棘手,但您需要使用自定义 Retrofit Converter Factory 和使用自定义 JsonDeserializer 的自定义 GsonBuilder。

此外,您应该定义一个使用 CustomJsonDeserializer 的接口(在我的示例中为CustomResonse)。这不是必需的,否则反序列化器将用于每个请求。

public class CustomConverterFactory {

    public static GsonConverterFactory create() {
        return GsonConverterFactory.create(createGsonCustomDeserializer());
    }

    public static Gson createGsonCustomJsonDeserializer() {
        return new GsonBuilder()
            .registerTypeAdapter(CustomResponse.class, new CustomJsonDeserializer())
            .serializeNulls()
            .create();
    }
}

对于反序列化器:

public class CustomJsonDeserializer implements JsonDeserializer<CustomResponse> {

@Override
public CustomResponse deserialize(final JsonElement json, final Type typeOfT,
        final JsonDeserializationContext context) throws JsonParseException {
    if (json.isJsonObject()) {
        JsonObject jsonObject = json.getAsJsonObject();

        // Here you have to distinguish your class somehow
        // Maybe read some Json field from your response
        if (jsonObject.has("name")) {
            JsonElement classes = jsonObject.get("name");
            ...
            return context.deserialize(json, MyName.class);
        }
        ...
        // Default fallback: Deserialize as a fallback object
        return context.deserialize(json, MyFallback.class);
    } else {
        throw new IllegalStateException();
    }
}

【讨论】:

  • 我知道这种方式..但是要做到这一点还有很长的路要走..仍然感谢您的回复..
  • 要么你在执行请求之前就知道你想要的班级,要么你必须这样做。
  • 谢谢你,我仍在寻找一些好的解决方案..我有这种方式..对于计划 b。
  • 问题,如果我在我的方法中使用此方法并且我从服务器收到的一些响应将是一个对象(IE 用户对象或事件对象列表),但有些将是直接布尔值/字符串),这种方法还能用吗?
【解决方案2】:

由于有这么多用户投了 DOWN VOTE,我已经解决了这个问题 我自己的问题,

像这样处理GET、POST或其他方法,

if (methodType.equalsIgnoreCase(CommonConfig.WsMethodType.GET)) {
                apicall = getClient(CommonConfig.WsPrefix).create(ApiInterface.class).makeGetRequest(url + CommonConfig.getQueryString(new Gson().toJson(requestBody)), getAllHeader);
 } else if (methodType.equalsIgnoreCase(CommonConfig.WsMethodType.POST)) {
                apicall = getClient(CommonConfig.WsPrefix).create(ApiInterface.class).makePostRequest(url, RequestBody.create(MediaType.parse("application/json"), new Gson().toJson(requestBody)), getAllHeader);
 }

这样处理响应。

apicall.enqueue(new Callback<ResponseBody>() {
                                @Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}

 @Override
 public void onFailure(Call<ResponseBody> call, Throwable t) {

}
}

改造代码

private Retrofit getClient(String WsPrefix) {
        //TODO 60 to 30 second at everywhere
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .build();

        retrofit = new Retrofit.Builder()
                .baseUrl(WsPrefix)
                .client(okHttpClient)
                .build();
        return retrofit;
    }

通用界面

interface ApiInterface {

        @GET
        Call<ResponseBody> makeGetRequest(@Url String url, @HeaderMap() Map<String, String> header);

        @POST
        Call<ResponseBody> makePostRequest(@Url String url, @Body RequestBody requestBody, @HeaderMap() Map<String, String> header);
}

ApiCallback

public interface ApiCallback {
      void success(String responseData);
      void failure(String responseData);
}

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 2018-11-04
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 2017-01-15
    • 2020-09-12
    相关资源
    最近更新 更多