Man*_*nos 17 java generics retrofit retrofit2
所以我有一个模特Model.
public class Model { .... }
Run Code Online (Sandbox Code Playgroud)
这有两个子类:
public class SubmodelA extend Model { .... }
Run Code Online (Sandbox Code Playgroud)
和
public class SubmodelB extend Model { .... }
Run Code Online (Sandbox Code Playgroud)
这三个都是在Data课堂上包装的.
public class ApiData<T extends Model> {
public T data;
}
Run Code Online (Sandbox Code Playgroud)
我的将军response wrapper看起来像这样:
public class ApiResponse<DATA> {
DATA data;
}
Run Code Online (Sandbox Code Playgroud)
"虚拟"api操作保持不变:
public interface Endpoints {
Call<ApiResponse<ApiData>> getData();
}
Run Code Online (Sandbox Code Playgroud)
我有一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
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));
}
}
Run Code Online (Sandbox Code Playgroud)
编译器遇到ApiCallbackProxy.with(callback)此错误:
所以我希望取决于在应用程序中使用此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) -> {};
Run Code Online (Sandbox Code Playgroud)
本ApiClient类有希望的侦听器ApiData<U>的响应。
问题是,没有U。您有一个Endpoint,并且端点没有泛型类型,并且返回ApiData时没有为泛型选择任何具体类型。
这是泛型出现错误的情况。通常的想法是使Endpoint通用:
public interface Endpoints<U> {
Call<ApiResponse<ApiData<U>>> getData();
}
Run Code Online (Sandbox Code Playgroud)
但是,该Retrofit怎么办?它将HTTP API转换为Java接口。再来看Retrofit的github仓库上最简单的示例,对我来说似乎很清楚,您应该放置访问某些真实HTTP端点的接口。这不是抽象的GET。
因此,您宁愿给它一个具体的类型而不是使其通用。做类似的事情:
public interface Endpoints {
Call<ApiResponse<ApiData<Model>>> getData();
}
Run Code Online (Sandbox Code Playgroud)
我希望Retrofit在回复您的请求时反序列化数据Model。因此,拥有具体的类而不是未设置的泛型类型变量对于成功的反序列化至关重要。但是,只能将其与以下任一监听器一起使用:
ApiResultListener<ApiResponse<Data<Model>>>
ApiResultListener<ApiResponse<Data<? super Model>>>
Run Code Online (Sandbox Code Playgroud)
另外,在问题的较早部分中,ApiResponse<Payload>泛型类型变量看起来像是Payload类的那部分,现在已经相当不完整了:)