不兼容的类型推断类型不符合等式约束

时间:2017-06-01 19:23:13

标签: java generics retrofit retrofit2

所以我有一个模型Model

public class Model { .... } 

这有两个子类:

public class SubmodelA extend Model { .... }

public class SubmodelB extend Model { .... }

这三个包含在Data类下。

public class ApiData<T extends Model> {

    public T data;

}

我的将军response wrapper看起来像这样:

public class ApiResponse<DATA> {

    DATA data;
}

&#34;虚拟&#34; api操作保持不变:

public interface Endpoints {

    Call<ApiResponse<ApiData>> getData();
}

我有retrofit2.Callback的实现来处理响应:

public class ApiCallbackProxy<T> implements retrofit2.Callback<T> {

    public interface ApiResultListener<RESPONSE_TYPE> {
        void onResult(RESPONSE_TYPE response, ApiError error);
    }

    private ApiResultListener<T> mListener;

    private ApiCallbackProxy(ApiResultListener<T> listener) {
        mListener = listener;
    }

    @Override
    public void onResponse(Call<T> call, Response<T> response) {

    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {

    }

    public static <T> ApiCallbackProxy<T> with(ApiResultListener<T> callback) {
        return new ApiCallbackProxy<>(callback);
    }
}

ApiClient

public class ApiClient {

    public Endpoints mRetrofit;

    public ApiClient() {
       Retrofit retrofit = new Retrofit.Builder().build();
       mRetrofit = retrofit.create(Endpoints.class);
    }

    public <U extends Model> void getData(ApiResultListener<ApiResponse<ApiData<U>>> callback) {
       //Compiler hits here
       mRetrofit.getData().enqueue(ApiCallbackProxy.with(callback));
    }
}

编译器在ApiCallbackProxy.with(callback)点击此错误:

enter image description here

所以我想要取决于在应用程序中使用此API调用的位置来返回模型的不同子类或模型本身。

public static void main (String[] args) {
    ApiClient apiClient = new ApiClient();
    apiClient.getData(listener2);
}


public static final ApiResultListener<ApiResponse<Data<SubmodelA>>> listener = (response, error) -> {};

public static final ApiResultListener<ApiResponse<Data<Model>>> listener2 = (response, error) -> {};

public static final ApiResultListener<ApiResponse<Data<SubmodelB>>> listener3 = (response, error) -> {};

1 个答案:

答案 0 :(得分:4)

ApiClient类有一个在响应中需要ApiData<U>的侦听器。

问题是,没有U。您有一个Endpoint,并且端点没有泛型类型,它只返回ApiData,没有选择通用的具体类型。

这是一个泛型出错的案例。通常的想法是使Endpoint通用:

public interface Endpoints<U> {
    Call<ApiResponse<ApiData<U>>> getData();
}

然而,Retrofit做了什么?它将HTTP API转换为Java接口。看看the most simple example at the github repo of Retrofit,我似乎很清楚你应该放置访问一些真正的HTTP端点的接口。它不是一些抽象的GET

所以你宁愿给它一个具体的类型而不是通用。做类似的事情:

public interface Endpoints {
    Call<ApiResponse<ApiData<Model>>> getData();
}

我希望Retrofit能够对您Model的响应中的数据进行反序列化。因此,拥有一个具体的类而不是一个未设置的泛型类型变量对于成功的反序列化至关重要。但是,您只能将侦听器用于以下任一项:

ApiResultListener<ApiResponse<Data<Model>>>
ApiResultListener<ApiResponse<Data<? super Model>>>

此外,在问题的旧部分,ApiResponse<Payload>部分,其中泛型类型变量看起来像Payload类,现在非常狡猾:)