Friday, January 20, 2017

How to make custom implementation of Retrofit2.Call<T>

Leave a Comment

I am using Retrofit2 and I want to Override its Call.enqueue method.

I did this so far:

Custom Call:

    public class CustomCall<T> implements Call<T> {          private final Call<T> delegate;         //..every method has delegate method invoked in it 

Apis:

        @GET         CustomCall<TKBaseResponse> testConnection(@Url String customUrl); 

But I keep getting these errors:

    Unable to create call adapter for CustomCall<....> 

and

    Could not locate call adapter for CustomCall<....> 

Any way on how can I do this properly? Thanks in advance!

2 Answers

Answers 1

First create a 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 is a class contains service endpoints.

final class ServiceApiEndpoints {      public static final String SERVICE_ENDPOINT = "your_app_url"; } 

Create an interface APIService

public interface APIService {  String GET_INFO = "get_info";      @GET(GET_INFO)     Call<ResInfo[]> getInfo(); } 

Create ResInfo model.

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

Call the request.

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

Answers 2

I am posting below an example to help you with retrofit implementation.

Create your resource like this (MyResource.java).

Call<TKBaseResponse> testConnection(@@Url String customUrl); 

Initialize Retrofit

private Resource getRetrofitResource(){    //Initialize retrofit.    final Retrofit = .....//your code to initialize retrofit    return retrofit.create(MyResource.class); } 

To implement call enqueue(async retrofit calls) you need to pass your resource response and a response handler which is your custom implementation into the enqueue method. I am posting my implementation of ResponseHandler alongside.

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

Create a method handle response.

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

Please let me know if you have any doubts around this.

Now from call your resource like below.

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..  }     }); 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment