I want to design API calls in such a way that it will be easy to handle success and failure responses easily from one place (instead of writing same code of call function for all APIs)
Here are the scenarios which I want to consider.
- Handle success / failure and error responses like 4xx, 5xx etc of all APIs at one central place.
- Want to cancel enqueue requests and also stop processing response if request is already sent in case of logout (because response parsing will modify some global data of app)
- If access token has expired and 401 response received from cloud, it should get new token and then call API again automatically with new token.
My current implementation is not satisfying above requirements. Is there any way to implement API calls which satisfy above requirements using Retrofit ? Please suggest me a good design for this.
Here is my current implementation :
- ApiInterface.java - It is an interface which contains different API calls definitions.
- ApiClient.java - To get retrofit client object to call APIs.
- ApiManager.java - It has methods to call APIs and parse their responses.
ApiInterface.java
public interface ApiInterface {
// Get Devices
@GET("https://example-base-url.com" + "/devices")
Call<ResponseBody> getDevices(@Header("Authorization) String token);
// Other APIs......
}
ApiClient.java
public class ApiClient {
private static Retrofit retrofitClient = null;
static Retrofit getClient(Context context) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), systemDefaultTrustManager())
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build();
retrofitClient = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();
}
}
ApiManager.java
public class ApiManager {
private static ApiManager apiManager;
public static ApiManager getInstance(Context context) {
if (apiManager == null) {
apiManager = new ApiManager(context);
}
return apiManager;
}
private ApiManager(Context context) {
this.context = context;
apiInterface = ApiClient.getClient(context).create(ApiInterface.class);
}
public void getDevices(ResponseListener listener) {
// API call and response handling
}
// Other API implementation
}
Update :
For 1st point, interceptor will be helpful to handle 4xx, 5xx responses globally according to this. But interceptor will be in the ApiClient file and to inform UI or API caller component, need to pass success or failure result in callback I mean response listener. How can I do that ? Any idea ?
For 3rd point, I know little bit about Retrofit Authenticator
. I think for this point it is suitable but it requires synchronous call to get new token using refresh token.
How can I make asynchronous call to synchronous ? (Note : this call is not retrofit call)