在改造中将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
}
用户是我的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,另一个是patientDetails。所以我必须创建两个模型类User和Patient。 因此,在改造中,我会有类似的东西
@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进行映射。
答案 0 :(得分:13)
Android:动态传递模型类以改进回调
有两种方法可以做到这一点.........
<强> 1。泛型强>
<强> 2。将所有POJO合并为一个......
<强>泛型强>
在泛型中,你必须通过类传递方法。请看示例.....
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类合并为一个并在Retrofit中使用它们。请看下面的例子......
我有两个API登录和用户......
在Login API中,我得到了像这样的JSON响应......
{“成功”:是的,“消息”:“身份验证成功”}
高于JSON,POJO看起来像这样
public class LoginResult{
private String message;
private boolean success;
//constructor , getter and setter
}
和Retrofit调用看起来像这样......
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
}
和Retrofit调用看起来像这样......
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与不同的变量类型相同则提供重复,这非常复杂)
答案 1 :(得分:10)
你可以像这样构建主要的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);
答案 2 :(得分:1)
首先创建界面:
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) {
}
});
答案 3 :(得分:1)
我的方法是制作一个名为ResponseData的POJO,你将拥有一个属性Object,所以你有:
@POST
Call<ResponseData> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap);
当您收到回复时,您必须将您的response.body()解析为所需的类。专业人士:你只需要一个请求,而不必解析响应。
答案 4 :(得分:1)
这样做:
@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) {
}
}
答案 5 :(得分:1)
为了概括您想要的内容,您只需序列化您的POJO,然后您就可以将POJO原样传递给方法。 当你使用Objects进行序列化时,它基本上将它转换为字符串,后来转换为一个大的Json字符串,更容易传输和操作。
一个简单的例子是:
示例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定义:
@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)
{
}
});
}
我通过听众返回回复,这是你可以做的一个例子,取决于你的回应。
希望这有帮助!
答案 6 :(得分:1)
您需要使用泛型。这样,您就可以将所需的类型传递给调用。
@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
}
顺便说一下,我没有改装专家(我主要使用自己的东西),但我认为你错了。
答案 7 :(得分:0)
使用标准泛型,有一点点黑客攻击
像这样定义你的界面
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提供的整个类型安全和合同验证..这实际上是最激动人心的事情..
答案 8 :(得分:0)
我使用以下方法: 首先,我实现了自定义调用
public class ProxyConvertCall<Tin,Tout> implements Call<Tout> {
Converter<Tin,Tout> converter;
Call<Tin> innerCall;
public ProxyConvertCall2(Call<Tin> jcall, Converter<Tin,Tout> converter){
this.innerCall = jcall;
this.converter = converter;
}
@Override
public Response<Tout> execute() throws IOException {
Response<Tin> response = innerCall.execute();
if (response.isSuccessful()){
return Response.success(converter.Convert(response.body()),response.raw());
}
else return Response.error(response.code(), response.errorBody());
}
@Override
public void enqueue(final Callback<Tout> callback) {
final Call<Tout> self = this;
this.innerCall.enqueue(new Callback<Tin>() {
@Override
public void onResponse(Call<Tin> call, Response<Tin> response) {
if (response.isSuccessful()){
callback.onResponse(self, Response.success(converter.Convert(response.body()), response.raw()));
}
else callback.onResponse(self, Response.error(response.code(), response.errorBody()));
}
@Override
public void onFailure(Call<Tin> call, Throwable t) {
callback.onFailure(self,t);
}
});
}
@Override
public boolean isExecuted() {
return innerCall.isExecuted();
}
@Override
public void cancel() {
innerCall.cancel();
}
@Override
public boolean isCanceled() {
return innerCall.isCanceled();
}
@Override
public Call<Tout> clone() {
return new ProxyConvertCall2<>(innerCall,converter);
}
@Override
public Request request() {
return innerCall.request();
}
}
它包裹Call<Tin>
并通过转换器将其结果转换为<Tout>
。
@FunctionalInterface
public interface Converter<Tin, Tout> {
public Tout Convert(Tin in);
}
对于您的服务,您必须创建服务接口,返回单个对象的JsonObject和数组的JsonArray
public interface ApiCalls {
@POST
Call<JsonObject> getDataFromServer(@Url String url, @Body HashMap<String,Object> hashMap);
@POST
Call<JsonArray> getArrayFromServer(@Url String url, @Body HashMap<String,Object> hashMap);
}
然后用泛型类包装它,将JsonElement中的转换器包装到任何类型<T>
:
public class ApiCallsGeneric<T> {
Converter<JsonObject,T> fromJsonObject;
Converter<JsonArray,List<T>> fromJsonArray;
ApiCalls service;
public ApiCallsGeneric(Class<T> classOfT, ApiCalls service){
this.service = service;
Gson gson = new GsonBuilder().create();
GenericListType<T> genericListTypeOfT = new GenericListType<T>(classOfT);
fromJsonObject = (t)->gson.fromJson(t,classOfT);
fromJsonArray =(t)->gson.fromJson(t,genericListTypeOfT);
}
public Call<T> getDataFromServer(String url, HashMap<String,Object> hashMap){
return new ProxyConvertCall<>(service.getDataFromServer(url, hashMap), fromJsonObject);
}
public Call<List<T>> getArrayFromServer(String url, HashMap<String,Object> hashMap){
return new ProxyConvertCall<>(service.getArrayFromServer(url, hashMap), fromJsonArray);
}
}
GenericListType是ParaterizedType。它用于将类型参数传递给List<T>
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class GenericListType<T> implements ParameterizedType {
private Type wrapped;
public GenericListType(Type wrapped) {
this.wrapped = wrapped;
}
public Type[] getActualTypeArguments() {
return new Type[] {wrapped};
}
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
}
然后,您可以使用所需的类型实例化ApiCallsGeneric
。
ApiCallsGeneric<User> userService= new ApiCallsGeneric<User>(User.class, retrofit.create(ApiCalls.class));
Call<User> call = userService.getDataFromServer(StringConstants.URL,hashMap);
call.enqueue(new Callback<User>() {
//Response and failure callbacks
}
答案 9 :(得分:0)
在Response中使用JsonElement会有所帮助:
public interface serviceApi {
// @GET("userinfo")
// Observable<userInfo> getUserIfo();
@GET("gmail/v1/users/me/profile")
Observable<Response<JsonElement>> getUserProfile(@HeaderMap
Map<String,String> Headers);
}
private void executeAPICall(String token) {
HashMap<String, String> headers = new HashMap<>();
Observable<Response<JsonElement>> observable = RetroFitInstance.getInstance().getAPI(token)
.getUserProfile(ImmutableMap.<String, String>of("Authorization", String.format("Bearer %s", token))).observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
Observer<Response<JsonElement>> observer = new Observer<Response<JsonElement>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.d("error:", e.getMessage());
}
@Override
public void onNext(Response<JsonElement> jsonElementResponse) {
UserProfile userProfile =
getObject(jsonElementResponse,UserProfile.class);
EmailTextView.setText("Email Address: " +
userProfile.getEmailAddress());
EmailTextView.setText("Email Address: " +
userProfile.getEmailAddress());
totalEmailsTextView.setText("Total Emails: " + userProfile.getMessagesTotal());
totalThreadsTextView.setText("Total Threads: " + userProfil
};
subscription = observable.subscribe(observer);
}
private <T> T getObject(Response<JsonElement> jsonElementResponse, Class<T>
t){
return new Gson().fromJson(jsonElementResponse.body().getAsJsonObject().toString(),t);
}