Android: динамический переход класса модели для повторного обратного вызова

В ретрофите для сопоставления ответа json на pojo обычно мы делаем это

@POST Call<User> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap); ApiCalls api = retrofit.create(ApiCalls.class); Call<User> call = api.getDataFromServer(StringConstants.URL,hashMap); call.enqueue(new Callback<User>() { //Response and failure callbacks } 

Где User – мой класс Pojo. Но для каждого другого запроса мне нужно сделать другое pojo и написать тот же код для переназначения вызова. Я хочу сделать один метод для вызова api и передать соответствующий класс pojo для перенастройки вызова. как это

 ApiCalls api = retrofit.create(ApiCalls.class); Call<*ClassPassed*> call = api.getDataFromServer(StringConstants.URL,hashMap); call.enqueue(new Callback<*ClassPassed*>() { //Response and failure callbacks } 

Поэтому теперь я могу любой класс pojo использовать один метод и получить ответ. Это просто, чтобы избежать повторного написания одного и того же кода снова и снова. Это возможно

Обновление Чтобы уточнить больше:

Предположим, мне нужно сделать два запроса. Первый заключается в том, чтобы получить userDetails, а другой – с терпеливымDetails.Таким образом, мне нужно создать два класса моделей User and Patient. Так что в retrofit api у меня будет что-то вроде этого

 @POST Call<User> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap); @POST Call<Patient> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap); 

И в моем классе FragmentUser и FragmentPatient я буду делать это

  ApiCalls api = retrofit.create(ApiCalls.class); Call<User> call = api.getDataFromServer(StringConstants.URL,hashMap); call.enqueue(new Callback<User>() { //Response and failure callbacks } ApiCalls api = retrofit.create(ApiCalls.class); Call<Patient> call = api.getDataFromServer(StringConstants.URL,hashMap); call.enqueue(new Callback<Patient>() { //Response and failure callbacks } 

Но здесь код воспроизводится просто из-за разных классов pojo. Мне нужно повторить один и тот же код во всех других фрагментах для разных запросов. Поэтому мне нужно сделать общий метод, в котором он может принять любой класс pojo, а затем из фрагмента я просто передам pojo для сопоставления.

Вы можете построить главное pojo, как это

 public class BaseResponse<T> { @SerializedName("Ack") @Expose private String ack; @SerializedName("Message") @Expose private String message; @SerializedName("Data") @Expose private T data; /** * * @return * The ack */ public String getAck() { return ack; } /** * * @param ack * The Ack */ public void setAck(String ack) { this.ack = ack; } /** * * @return * The message */ public String getMessage() { return message; } /** * * @param message * The Message */ public void setMessage(String message) { this.message = message; } /** * * @return * The data */ public T getData() { return data; } /** * * @param data * The Data */ public void setData(T data) { this.data = data; } } 

И назовите это

  Call<BaseResponse<SetupDetails>> getSetup(@Query("site_id") int id,@Query("ino") String ii); 

Первый интерфейс:

 public interface ItemAPI { @GET("setup.php") Call<SetupDetails> getSetup(@Query("site_id") int id,@Query("ino") String ii); @GET("setup.php") void setMy(@Query("site_id") int id, Callback<List<SetupDetails>> sd); } 

Теперь создадим класс:

 public class Apiclient { private static final String BASE_URL ="http://www.YOURURL.COM/"; private static Retrofit retrofit = null; public static Retrofit getClient() { OkHttpClient.Builder httpClient2 = new OkHttpClient.Builder(); httpClient2.addNetworkInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request.Builder builder = chain.request().newBuilder(); builder.addHeader("site_id","1"); return chain.proceed(builder.build()); } }); OkHttpClient client = httpClient2.build(); if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } 

Теперь в любой деятельности просто используйте:

 ItemAPI itemAPI = Apiclient.getClient().create(ItemAPI.class); Call<AllProducts> call=itemAPI.getSetup(1,count); call.enqueue(new Callback<AllProducts>() { @Override public void onResponse(Call<AllProducts> call, Response<AllProducts> response) { try { if (response.body().getItem().size()>0){ } }catch (Exception e){ e.printStackTrace(); } } @Override public void onFailedAfterRetry(Throwable t) { } }); 

Мой подход заключается в создании POJO под названием ResponseData, в котором у вас будет атрибут Object, поэтому у вас есть:

 @POST Call<ResponseData> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap); 

Когда вы получите ответ, вам нужно проанализировать ваш response.body () в нужном классе. Итак, профи: у вас есть только один запрос, вместо этого вам нужно разобрать ответ.

Делай это так :

  @POST Call<Object> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap); ApiCalls api = retrofit.create(ApiCalls.class); Call<Object> call = api.getDataFromServer(StringConstants.URL,hashMap); call.enqueue(new Callback<User>() { @Override public void onResponse(Call<Object> call, Response<Object> response) { YourModel modelObject = (YourModel) response.body(); } @Override public void onFailure(Call<Object> call, Throwable t) { } } 

Чтобы упорядочить то, что вы хотите, вы можете просто сериализовать свой POJO, а затем вы можете просто передать POJO методу как есть. При сериализации с объектами он в основном преобразует его в строку, которые позже преобразуются в одну большую Json String, которую легче переносить и манипулировать.

Быстрый пример:

Пример POJO, реализующий сериализацию, здесь вы должны убедиться, что строки в Map<String,Object> соответствуют тому, что ожидает сервер, и этот метод должен быть различным в каждом POJO:

 public class YourPojo implements ObjectSerializer { private static final long serialVersionUID = -1481977114734318563L; private String itemName; private int itemId; @Override public Map<String, Object> objectSerialize() { Map<String, Object> map = new HashMap<>(); map.put("itemid", itemId); // server will be looking for "itemid" map.put("itemname", itemName); // server will be looking for "itemname" } //other stuff you need.... } 

Интерфейс сериализации (чтобы вы могли реализовать его через другие POJO)

 public interface ObjectSerializer extends Serializable { public Map<String, Object> objectSerialize(); } 

И парсер Json, которого вы, наверное,

 public class JsonParser { public static JSONObject serializeToJsonString(Map<String, Object> jsonParams) { Gson gson = new Gson(); String json = gson.toJson(jsonParams); JSONObject object; try { object = new JSONObject(json); } catch (Exception e) { object = new JSONObject(jsonParams); } return (object); } } 

И, наконец, ваш API defintion:

 @POST("users/createitem") Call<ResponseBody> someCall(@Body RequestBody params); 

И метод, который должен сидеть в общем классе, который управляет вашими запросами:

 public void someMethodName(YourPojo item, final CustomEventListener<String> listener) { JSONObject object = JsonParser.serializeToJsonString(item.objectSerialize()); RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8";), object.toString()); Call<ResponseBody> requestCall = serviceCaller.someCall(body); requestCall.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse) { try { String response = rawResponse.body().string(); //do what you want with this string listener.getResult(response); } catch (Exception e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable throwable) { } }); } 

Я возвращаю ответ через слушателя, это один из примеров того, что вы можете сделать в зависимости от вашего ответа.

Надеюсь это поможет!

Вам нужно использовать дженерики. Таким образом, вы можете передать желаемый тип в вызов.

 @POST Call<T> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap, Class<T> requestClass); ApiCalls api = retrofit.create(ApiCalls.class); Call<T> call = api.getDataFromServer(StringConstants.URL,hashMap); call.enqueue(new Callback<T>() { //Response and failure callbacks } 

Кстати, я не специалист по дооснащению (я использую свой собственный материал в основном), но я думаю, что вы используете его неправильно.

Есть два способа сделать это ………

1. Дженерики

2. Объедините все POJO в один ……

Дженерики

В Generics вам нужно передать метод с классом. Пожалуйста, смотрите на примере …..

 ApiCalls api = retrofit.create(ApiCalls.class); Call<User> call = api.getDataFromServer(StringConstants.URL,hashMap); callRetrofit(call,1); public static <T> void callRetrofit(Call<T> call,final int i) { call.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, Response<T> response) { if(i==1){ User user = (User) response.body(); // use the user object for the other fields }else if (i==2){ Patient user = (Patient) response.body(); } } @Override public void onFailure(Call<T> call, Throwable t) { } }); } 

ПРИМЕЧАНИЕ. – Вышеописанный вызов TypeCast возвращает ваш ответ в YOUR OBJECT , так что вы можете получить доступ к его полю и методам

Объедините все POJO в один

Он очень прост в использовании . Вы должны объединить весь свой класс POJO в один и использовать их в Дополнении. Пожалуйста, посмотрите ниже пример ….

У меня есть два входа и пользователя API …

В Login API у меня есть ответ JSON вроде этого …

{"Success": True, "message": "Authentication successful"}

Над JSON, POJO выглядят так

 public class LoginResult{ private String message; private boolean success; //constructor , getter and setter } 

И «Дооснащение» выглядят так …..

  call.enqueue(new Callback<LoginResult>() { @Override public void onResponse(Call<LoginResult> call, Response<LoginResult> response) { } @Override public void onFailure(Call<LoginResult> call, Throwable t) { } }); 

В User API у меня есть ответ JSON вроде этого …

{"Name": "sushildlh", "place": "hyderabad"}

Над JSON, POJO выглядят так

  public class UserResult{ private String name; private String place; //constructor , getter and setter } 

И «Дооснащение» выглядят так …..

  call.enqueue(new Callback<UserResult>() { @Override public void onResponse(Call<UserResult> call, Response<UserResult> response) { } @Override public void onFailure(Call<UserResult> call, Throwable t) { } }); 

Просто объедините оба вышеуказанных ответа JSON в один …..

 public class Result{ private String name; private String place; private String message; private boolean success; //constructor , getter and setter } 

И используйте результат внутри вашего вызова API …

  call.enqueue(new Callback<Result>() { @Override public void onResponse(Call<Result> call, Response<Result> response) { } @Override public void onFailure(Call<Result> call, Throwable t) { } }); 

Примечание. – Вы напрямую объединяете свой класс 2 POJO и получаете доступ к нему. (Это очень сложно, если у вас очень большой ответ и дублирование, если какой-то KEY одинаковый с другим типом Variable)

Используйте стандартные дженерики, немного взломав

Определите свой интерфейс следующим образом:

 public interface ApiCalls<T> { @POST Call<T> getResult getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap); } 

И вызов для создания клиента api использует вспомогательный метод

 class HelperMethods { @SuppressWarnings("unchecked") private static <T> ApiCalls<T> getClient() { return retrofit.create((Class<ApiCalls<T>>)(Class<?>)ApiCalls.class); } } ApiCalls<User> api = HelperMethods.getClient(); 

Но, несмотря на то, сколько раз было сказано здесь, я снова скажу это … Не делайте этого. Вы отказываетесь от всей безопасности и проверки контракта, которую предлагает Retrofit. Это на самом деле Самое интересное в этом.