如何自定义实现 Retrofit2.Call<T>
How to make custom implementation of Retrofit2.Call<T>
我正在使用 Retrofit2,我想覆盖它的 Call.enqueue 方法。
到目前为止我这样做了:
自定义调用:
public class CustomCall<T> implements Call<T> {
private final Call<T> delegate;
//..every method has delegate method invoked in it
蜜蜂:
@GET
CustomCall<TKBaseResponse> testConnection(@Url String customUrl);
但我不断收到这些错误:
Unable to create call adapter for CustomCall<....>
和
Could not locate call adapter for CustomCall<....>
关于如何正确执行此操作的任何方法?提前致谢!
我在下面发布了一个示例,以帮助您进行改造实施。
像这样创建您的资源 (MyResource.java)。
Call<TKBaseResponse> testConnection(@@Url String customUrl);
初始化改造
private Resource getRetrofitResource(){
//Initialize retrofit.
final Retrofit = .....//your code to initialize retrofit
return retrofit.create(MyResource.class);
}
要实现调用入队(异步改装调用),您需要将资源响应和响应处理程序(这是您的自定义实现)传递到入队方法中。我将 ResponseHandler 的实现贴在旁边。
public abstract class ResponseHandler<T> {
private static final String TAG = ResponseHandler.class.getSimpleName();
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private final Context context;
public ResponseHandler() {
this(null);
}
public ResponseHandler(final Context context) {
this.context = context;
}
public abstract void onResponse(final T response);
public void onError(final ErrorResponse errorResponse) {
if (context == null) {
return;
}
Log.e(TAG, "An error occurred while invoking service. Error Code: " + errorResponse.getErrorCode() + LINE_SEPARATOR + "Message: " + errorResponse.getMessage() + LINE_SEPARATOR);
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setTitle(R.string.title_server_error_dialog);
alertBuilder.setMessage(R.string.network_error_message);
alertBuilder.setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
alertBuilder.show();
}
public void onFailure(Throwable throwable) {
if (context == null) {
return;
}
Log.e(TAG, "An error occurred while invoking service", throwable);
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setTitle(R.string.title_network_error_dialog);
alertBuilder.setMessage(R.string.network_error_message);
alertBuilder.setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
alertBuilder.show();
}
}
创建方法句柄响应。
protected <T> void handleResponse(Call<T> call, final ResponseHandler<T> responseHandler) {
call.enqueue(new Callback<T>() {
@Override
public void onResponse(final Call<T> call, final Response<T> response) {
if (response.isSuccess()) {
if (responseHandler != null ) {
responseHandler.onResponse(response.body());
}
} else {
final ErrorResponse errorResponse = parseError(response);
if (responseHandler != null) {
responseHandler.onError(errorResponse);
}
}
}
@Override
public void onFailure(final Call<T> call, final Throwable throwable) {
if (responseHandler != null) {
responseHandler.onFailure(throwable);
}
}
});
}
如果您对此有任何疑问,请告诉我。
现在像下面这样调用您的资源。
final MyResource resource = getRetrofitResource();
final Call<TKBaseResponse> response = resource .testConnection("ANY_URL_OF_YOUR_CHOICE");
handleResponse(response, new ResponseHandler<TKBaseResponse>(){
public void onResponse(final TKBaseResponse response){
//Do whatever you want to do here..
}
});
首先创建一个ServiceManager class -
public final class ServiceManager {
private static ServiceManager sServiceManager;
/**
* Gets the instance of the web services implementation.
*
* @return the singleton instance.
*/
public static ServiceManager get() {
if (sServiceManager == null) {
sServiceManager = new ServiceManager();
}
return sServiceManager;
}
/**
* Creates the services for a given HTTP Url, useful when testing
* through multiple endpoints and unit testing
*
* @param clazz the service class.
* @param <T> type of the service.
* @return the created services implementation.
*/
public <T> T createService(Class<T> clazz) {
return createService(clazz, HttpUrl.parse(ServiceApiEndpoints.SERVICE_ENDPOINT));
}
/**
* Creates the services for a given HTTP Url, useful when testing
* through multiple endpoints and unit testing
*
* @param clazz the service class.
* @param httpUrl the endpoint
* @param <T> type of the service.
* @return the created services implementation.
*/
public <T> T createService(Class<T> clazz, HttpUrl httpUrl) {
Retrofit retrofit = getRetrofit(httpUrl);
return retrofit.create(clazz);
}
public <T> T createService(Class<T> clazz, Retrofit retrofit) {
return retrofit.create(clazz);
}
private Retrofit getRetrofit(HttpUrl httpUrl) {
return new Retrofit.Builder()
.baseUrl(httpUrl)
.client(createClient())
.addConverterFactory(getConverter())
.build();
}
public Retrofit getPlainRetrofit(HttpUrl httpUrl) {
return new Retrofit.Builder()
.baseUrl(httpUrl)
.client(new OkHttpClient.Builder().build())
.addConverterFactory(getConverter())
.build();
}
private Converter.Factory getConverter() {
return GsonConverterFactory.create();
}
private OkHttpClient createClient() {
return new OkHttpClient.Builder().addInterceptor(new RequestInterceptor()).build();
}
}
ServiceApiEndpoints 是一个 class 包含服务端点。
final class ServiceApiEndpoints {
public static final String SERVICE_ENDPOINT = "your_app_url";
}
创建接口 APIService
public interface APIService {
String GET_INFO = "get_info";
@GET(GET_INFO)
Call<ResInfo[]> getInfo();
}
创建 ResInfo 模型。
public class ResInfo {
private static final String FIELD_CONTENT = "content";
public String getContent() {
return mContent;
}
public void setContent(final String content) {
mContent = content;
}
@SerializedName(FIELD_CONTENT)
private String mContent;
public ResInfo(){
}
}
调用请求。
private Call<ResInfo[]> mGetInfoAPICall;
APIService apiService=ServiceManager.get().createService(APIService.class);
mGetInfoAPICall = apiService.getInfo();
mGetInfoAPICall.enqueue(new Callback<ResInfo[]>() {
@Override
public void onResponse(Call<ResInfo[]> call, Response<ResInfo[]> response) {
}
@Override
public void onFailure(Call<ResInfo[]> call, Throwable t) {
}
});
我正在使用 Retrofit2,我想覆盖它的 Call.enqueue 方法。
到目前为止我这样做了:
自定义调用:
public class CustomCall<T> implements Call<T> {
private final Call<T> delegate;
//..every method has delegate method invoked in it
蜜蜂:
@GET
CustomCall<TKBaseResponse> testConnection(@Url String customUrl);
但我不断收到这些错误:
Unable to create call adapter for CustomCall<....>
和
Could not locate call adapter for CustomCall<....>
关于如何正确执行此操作的任何方法?提前致谢!
我在下面发布了一个示例,以帮助您进行改造实施。
像这样创建您的资源 (MyResource.java)。
Call<TKBaseResponse> testConnection(@@Url String customUrl);
初始化改造
private Resource getRetrofitResource(){
//Initialize retrofit.
final Retrofit = .....//your code to initialize retrofit
return retrofit.create(MyResource.class);
}
要实现调用入队(异步改装调用),您需要将资源响应和响应处理程序(这是您的自定义实现)传递到入队方法中。我将 ResponseHandler 的实现贴在旁边。
public abstract class ResponseHandler<T> {
private static final String TAG = ResponseHandler.class.getSimpleName();
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private final Context context;
public ResponseHandler() {
this(null);
}
public ResponseHandler(final Context context) {
this.context = context;
}
public abstract void onResponse(final T response);
public void onError(final ErrorResponse errorResponse) {
if (context == null) {
return;
}
Log.e(TAG, "An error occurred while invoking service. Error Code: " + errorResponse.getErrorCode() + LINE_SEPARATOR + "Message: " + errorResponse.getMessage() + LINE_SEPARATOR);
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setTitle(R.string.title_server_error_dialog);
alertBuilder.setMessage(R.string.network_error_message);
alertBuilder.setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
alertBuilder.show();
}
public void onFailure(Throwable throwable) {
if (context == null) {
return;
}
Log.e(TAG, "An error occurred while invoking service", throwable);
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setTitle(R.string.title_network_error_dialog);
alertBuilder.setMessage(R.string.network_error_message);
alertBuilder.setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
alertBuilder.show();
}
}
创建方法句柄响应。
protected <T> void handleResponse(Call<T> call, final ResponseHandler<T> responseHandler) {
call.enqueue(new Callback<T>() {
@Override
public void onResponse(final Call<T> call, final Response<T> response) {
if (response.isSuccess()) {
if (responseHandler != null ) {
responseHandler.onResponse(response.body());
}
} else {
final ErrorResponse errorResponse = parseError(response);
if (responseHandler != null) {
responseHandler.onError(errorResponse);
}
}
}
@Override
public void onFailure(final Call<T> call, final Throwable throwable) {
if (responseHandler != null) {
responseHandler.onFailure(throwable);
}
}
});
}
如果您对此有任何疑问,请告诉我。
现在像下面这样调用您的资源。
final MyResource resource = getRetrofitResource();
final Call<TKBaseResponse> response = resource .testConnection("ANY_URL_OF_YOUR_CHOICE");
handleResponse(response, new ResponseHandler<TKBaseResponse>(){
public void onResponse(final TKBaseResponse response){
//Do whatever you want to do here..
}
});
首先创建一个ServiceManager class -
public final class ServiceManager {
private static ServiceManager sServiceManager;
/**
* Gets the instance of the web services implementation.
*
* @return the singleton instance.
*/
public static ServiceManager get() {
if (sServiceManager == null) {
sServiceManager = new ServiceManager();
}
return sServiceManager;
}
/**
* Creates the services for a given HTTP Url, useful when testing
* through multiple endpoints and unit testing
*
* @param clazz the service class.
* @param <T> type of the service.
* @return the created services implementation.
*/
public <T> T createService(Class<T> clazz) {
return createService(clazz, HttpUrl.parse(ServiceApiEndpoints.SERVICE_ENDPOINT));
}
/**
* Creates the services for a given HTTP Url, useful when testing
* through multiple endpoints and unit testing
*
* @param clazz the service class.
* @param httpUrl the endpoint
* @param <T> type of the service.
* @return the created services implementation.
*/
public <T> T createService(Class<T> clazz, HttpUrl httpUrl) {
Retrofit retrofit = getRetrofit(httpUrl);
return retrofit.create(clazz);
}
public <T> T createService(Class<T> clazz, Retrofit retrofit) {
return retrofit.create(clazz);
}
private Retrofit getRetrofit(HttpUrl httpUrl) {
return new Retrofit.Builder()
.baseUrl(httpUrl)
.client(createClient())
.addConverterFactory(getConverter())
.build();
}
public Retrofit getPlainRetrofit(HttpUrl httpUrl) {
return new Retrofit.Builder()
.baseUrl(httpUrl)
.client(new OkHttpClient.Builder().build())
.addConverterFactory(getConverter())
.build();
}
private Converter.Factory getConverter() {
return GsonConverterFactory.create();
}
private OkHttpClient createClient() {
return new OkHttpClient.Builder().addInterceptor(new RequestInterceptor()).build();
}
}
ServiceApiEndpoints 是一个 class 包含服务端点。
final class ServiceApiEndpoints {
public static final String SERVICE_ENDPOINT = "your_app_url";
}
创建接口 APIService
public interface APIService {
String GET_INFO = "get_info";
@GET(GET_INFO)
Call<ResInfo[]> getInfo();
}
创建 ResInfo 模型。
public class ResInfo {
private static final String FIELD_CONTENT = "content";
public String getContent() {
return mContent;
}
public void setContent(final String content) {
mContent = content;
}
@SerializedName(FIELD_CONTENT)
private String mContent;
public ResInfo(){
}
}
调用请求。
private Call<ResInfo[]> mGetInfoAPICall;
APIService apiService=ServiceManager.get().createService(APIService.class);
mGetInfoAPICall = apiService.getInfo();
mGetInfoAPICall.enqueue(new Callback<ResInfo[]>() {
@Override
public void onResponse(Call<ResInfo[]> call, Response<ResInfo[]> response) {
}
@Override
public void onFailure(Call<ResInfo[]> call, Throwable t) {
}
});