Android 无法使所有型号的改型2接口通用
我在我的应用程序中使用了改型2,它工作得非常好,但我试图通过传递一个动态模型,为所有类型的GET方法请求使用一个接口。当我使用下面的代码尝试它时,它在运行时给出了错误Android 无法使所有型号的改型2接口通用,android,retrofit,retrofit2,Android,Retrofit,Retrofit2,我在我的应用程序中使用了改型2,它工作得非常好,但我试图通过传递一个动态模型,为所有类型的GET方法请求使用一个接口。当我使用下面的代码尝试它时,它在运行时给出了错误 public interface LoadDataServiceTest<T> { @GET Call<T> getModel(@Url String url, @QueryMap Map<String, String> options); } 公共接口
public interface LoadDataServiceTest<T> {
@GET
Call<T> getModel(@Url String url, @QueryMap Map<String, String> options);
}
公共接口LoadDataServiceTest{
@得到
调用getModel(@Url字符串Url,@QueryMap映射选项);
}
型号:
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;
}
}
公共类模型测试{
@序列化名称(“状态”)
私有字符串状态;
@SerializedName(“消息”)
私有字符串消息;
@SerializedName(“用户”)
私有T数据;
公共字符串getStatus(){
返回状态;
}
公共字符串getMessage(){
返回消息;
}
公共T getData(){
返回数据;
}
}
但当我创建如下服务时,我得到了错误。我如何解决这个问题,实现这个目标的最佳方法是什么
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);
LoadDataServiceTest服务=改造.create((Class)(Class)api.LoadDataServiceTest.Class);
映射参数=新的HashMap();
参数put(“用户id”,userId);
Call Call=service.getModel(api.GET_用户,参数);
错误:
致命异常:主
进程:com.iu.colgatepolmolive,PID:16808
java.lang.RuntimeException:无法启动活动
组件信息{com.iu.colgateplmolive/com.iu.hfl_ccp.LoginActivity}:
java.lang.IllegalArgumentException:方法返回类型不能为
包括类型变量或通配符:2.Call
对于方法LoadDataServiceTest.getModel
在
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
在
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
位于android.app.ActivityThread.-wrap12(ActivityThread.java)
在
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)
位于android.os.Handler.dispatchMessage(Handler.java:102)
位于android.os.Looper.loop(Looper.java:154)
位于android.app.ActivityThread.main(ActivityThread.java:6121)
位于java.lang.reflect.Method.invoke(本机方法)
在
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
原因:java.lang.IllegalArgumentException:方法返回类型必须为
不包括类型变量或通配符:2.Call
对于方法LoadDataServiceTest.getModel
在2.ServiceMethod$Builder.methodError处(ServiceMethod.java:720)
在2.ServiceMethod$Builder.methodError处(ServiceMethod.java:711)
在
改造2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:224)
在2.ServiceMethod$Builder.build上(ServiceMethod.java:160)
在Refundation2.Refundation.loadServiceMethod(Refundation.java:166)中
在reformation2.reformation$1.invoke(reformation.java:145)
位于java.lang.reflect.Proxy.invoke(Proxy.java:813)
位于$Proxy5.getModel(未知源)
我使用以下方法。
首先,我实现了自定义调用
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();
}
}
然后可以使用所需的类型实例化LoadDataServiceTestGeneric 在短时间内检查这个,这是不可能的。谢谢你的参考。
@FunctionalInterface
public interface Converter<Tin, Tout> {
public Tout Convert(Tin in);
}
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);
}
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);
}
}
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;
}
}
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;
}
}