当前位置: 首页 > 知识库问答 >
问题:

无法使reverfit2接口适用于所有型号

丌官哲彦
2023-03-14

我在我的应用程序中使用了reverfit2,它工作得真的很好,但是我试图通过传递一个动态模型,为所有类型的GET方法请求使用一个单一的接口。当我尝试使用下面的代码时,它在运行时给出错误

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

错误:

致命异常:主进程:com.iu.colgatePalmolive,pid:16808 java.lang.runtimeException:无法启动activity ComponentInfo{com.iu.colgatePalmolive/com.iu.hfl_ccp.loginActivity}:java.lang.IllegalArgumentException:方法返回类型不能包含类型变量或通配符:Retrofit2.调用Android.app.ActivityThread.PerformLaunchActivity(ActivityThread.java:2666)在Android.app.ActivityThread.HandleLaunchActivityava.lang.IllegalArgumentException:方法返回类型不能包含类型变量或通配符:Retrofit2.ServiceMethod$Builder.MethodError(ServiceMethod.java:720)在Retrofit2.ServiceMethod$Builder.MethodError(ServiceMethod.java:711)在Retrofit2.ServiceMethod$Builder.CreateCallAdapter(ServiceMethod.java:224)在Retrofit2.ServiceMethod.java:160)在Retrofit2.Retrofit.LoadServiceMethod

共有1个答案

秦景同
2023-03-14

我使用以下方法。首先,我实现了自定义调用

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

它使用转换器将调用 调整为调用

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

对于您的服务,您必须创建服务接口,该接口为单个对象返回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);


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

}

ModelTestType是ParameterizedType。用于将类型参数传递给modeltesttype 的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。

 类似资料:
  • 在本地我使用mysql,所以当我使用 不幸的是,应用程序也必须在不同的数据库上运行,我还没有被告知哪些数据库是“完全”的。 是否有可能制作出具有类似效果的东西,但可以在大多数数据库中使用?我怎样才能做到这一点?

  • 问题内容: 我正在使用Spring框架(2.5)及其AOP功能。我有一个切入点表达,例如 凡ItemReader接口是一个Spring接口,它的签名是: 该接口有一个名为“ read”的方法,我要对其应用此建议:方法签名为: 但是,当我使用上述切入点表达式运行应用程序时,出现以下异常: java.lang.IllegalArgumentException:警告与此类型名称不匹配:org.sprin

  • 问题内容: 我试图找出如何列出Python中所有可用的无线网络。我正在使用Windows 8.1。 是否有我可以调用的内置函数或通过库? 请给我看看打印列表的代码。 问题答案: 您将需要该模块和一个Windows命令: 只是获得SSID的一些额外功能。 https://docs.python.org/2/library/subprocess.html

  • 我有一个C程序,通过响应信号来运行。一些信号导致父级分叉。这允许在父级继续响应信号的同时进行其他处理。 当父母被发送SIGTERM时,我希望分叉的孩子也收到一个SIGTERM。在父级退出之前,子级完成处理 SIGTERM 并不重要。 但是,使用下面的代码,当我从父代调用< code>kill(0,SIGTERM)时,子代没有收到SIGTERM。从< code>kill联机帮助页来看,似乎所有的孩子

  • 问题内容: 我对Spring框架很陌生,遇到了以下问题。 我有一个接口,由class 和实现。 我将以下bean定义添加到 我想自动连接以下两个实现类。 上面的代码抛出错误为 无法自动写入字段:com.abc.ClassA1 com.abc.SomeClass.classA1; 嵌套的异常是org.springframework.beans.factory.NoSuchBeanDefinition

  • 问题内容: 目前我有这样的事情 main.go 还有我的工作包 和 我正在传递给NewJob的函数是在goroutine上每2秒执行一次,但是我想访问我传递的匿名结构…但是当我尝试访问时 编号 我越来越 t.Id未定义(类型interface {}是没有方法的接口) 但是打印t给我预期的结果 {1} 问题答案: 您必须先将其声明为兼容类型,然后才能访问其字段。