gpt4 book ai didi

android - 无法使所有模型的 Retrofit2 接口(interface)通用

转载 作者:行者123 更新时间:2023-12-05 07:41:26 26 4
gpt4 key购买 nike

我在我的应用程序中使用 Retrofit2,它工作得非常好,但我试图通过传递动态模型对所有类型的 GET 方法请求使用单一接口(interface)。当我使用下面的代码尝试它时,它在运行时给出错误

public interface LoadDataServiceTest<T> {
@GET
Call<T> getModel(@Url String url, @QueryMap Map<String, String> options);
}

型号:

public class ModelTest<T> {
@SerializedName("status")
private String status;
@SerializedName("message")
private String message;
@SerializedName("users")
private T data;

public String getStatus() {
return status;
}

public String getMessage() {
return message;
}

public T getData() {
return data;
}
}

但是当我如下创建服务时,我得到了错误。我该如何解决它以及实现此目标的最佳方法是什么。

LoadDataServiceTest<ModelTest<JsonArray>> service = retrofit.create((Class<LoadDataServiceTest<ModelTest<JsonArray>>>) (Class<?>) APIs.LoadDataServiceTest.class);
Map<String, String> parameters = new HashMap<>();
parameters.put("user_id",userId);
Call<ModelTest<JsonArray>> call = service.getModel(APIs.GET_USERS, parameters);

错误:

FATAL EXCEPTION: main Process: com.iu.colgatepalmolive, PID: 16808 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.iu.colgatepalmolive/com.iu.hfl_ccp.LoginActivity}: java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: retrofit2.Call for method LoadDataServiceTest.getModel at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: retrofit2.Call for method LoadDataServiceTest.getModel at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:720) at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:711) at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:224) at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:160) at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166) at retrofit2.Retrofit$1.invoke(Retrofit.java:145) at java.lang.reflect.Proxy.invoke(Proxy.java:813) at $Proxy5.getModel(Unknown Source)

最佳答案

我使用以下方法。起初我实现了自定义调用

public class ProxyConvertCall<Tin,Tout> implements Call<Tout> {
Converter<Tin,Tout> converter;
Call<Tin> innerCall;

public ProxyConvertCall(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 ProxyConvertCall<>(innerCall,converter);
}

@Override
public Request request() {
return innerCall.request();
}
}

它适应Call<Tin>Call<Tou>使用转换器。

@FunctionalInterface 
public interface Converter<Tin, Tout> {
public Tout Convert(Tin in);
}

对于您的服务,您必须创建服务接口(interface),它返回单个对象的 JsonObject 和数组的 JsonArray

  public interface LoadDataServiceTest {
@GET
public Call<JsonObject> getModelTest(@Url String url, @QueryMap Map<String, String> options);

@GET
public Call<JsonObject> getModel(@Url String url, @QueryMap Map<String, String> options);

@GET
public Call<JsonArray> getModels(@Url String url, @QueryMap Map<String, String> options);


}

然后用通用类包装它,从 JsonElement 到任何类型的转换器 <T>ModelTest<T> :

   public class LoadDataServiceTestGeneric<T> {
Converter<JsonObject,ModelTest<T>> fromJsonObjectToModelTest;
Converter<JsonObject,T> fromJsonObject;
Converter<JsonArray,List<T>> fromJsonArray;
LoadDataServiceTest service;

public LoadDataServiceTestGeneric(Class<T> classOfT, LoadDataServiceTest 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<ModelTest<T>> getModelTest(String url, Map<String, String> options){
return new ProxyConvertCall<>(service.getModelTest(url, options), fromJsonObjectToModelTest);
}

public Call<T> getModel(String url, Map<String, String> options){
return new ProxyConvertCall<>(service.getModel(url, options), fromJsonObject);
}

Call<List<T>> getModels(String url, Map<String, String> options){
return new ProxyConvertCall<>(service.getModels(url, options), fromJsonArray);
}

}

GenericListType 是参数化类型。它用于将类型参数传递给 List<T> 的 gson

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;
}

}

ModelTestType 是参数化类型。它用于将类型参数传递给 ModelTestType<T> 的 gson

public class ModelTestType  implements ParameterizedType {

private Type wrapped;

public ModelTestType(Type wrapped) {
this.wrapped = wrapped;
}

public Type[] getActualTypeArguments() {
return new Type[] {wrapped};
}

public Type getRawType() {
return ModelTest.class;
}

public Type getOwnerType() {
return null;
}

}

然后您可以使用您想要的类型实例化 LoadDataServiceTestGeneric。

关于android - 无法使所有模型的 Retrofit2 接口(interface)通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45342524/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com