I am using Retrofit 1.9 in a big project and must check some data from response header even if call is failed - to analyse request code for example. We already know structure for async calls:
RestClient.get().asyncRequest(requestParams, new Callback<GenericResponse>() {
#Override
public void success(MyPojo pojo, Response response) {
//we can use pojo object or use whole response
}
#Override
public void failure(RetrofitError error) {
//we can handle only error but NOT response
}
});
How can we analyse Response in both cases here?
One solution is to use Profiler when RestAdapter is created, smth like:
RestAdapter restAdapter = new RestAdapter.Builder()
//other stuff
.setProfiler(new Profiler() {
#Override
public Object beforeCall() {
return null;
}
#Override
public void afterCall(RequestInformation requestInfo, long elapsedTime, int statusCode, Object beforeCallData) {
//get what I need
}
})
.build();
But maybe there is another solution to get response in failure() method. Any advices wil be apreciated!
You can get response body retriving it from RetrofitError.
#Override
public void failure(RetrofitError error) {
//here you get your response
Response response = error.getResponse();
//use data from response
int code = response.getStatus();
List<Header> = response.getHeaders();
// ...
}
I think this will solve your problem
RestAdapter restAdapter = new RestAdapter.Builder()
//other stuff
.setProfiler(new Profiler() {
#Override
public Object beforeCall() {
return null;
}
#Override
public void afterCall(RequestInformation requestInfo, long elapsedTime, int statusCode, Object beforeCallData) {
//get what I need
}
})
.setLogLevel(RestAdapter.LogLevel.FULL).build();
Now you can get the response
public void failure(RetrofitError error) {
String json = new String(((TypedByteArray)error.getResponse().getBody()).getBytes());
Log.v("failure", json.toString());
}
failure method in retrofit only tells the error occurred if want to see you can check that the arguments of error method in retrofit or you can call again the service if you want to call again when it comes to failure.
Related
I would like to handle my response from server , but I don't know how JSON (from server) its looks like. So I tried to display response as String , but I cant do it. Is it possible to display response as String? And then handle the response correctly. thanks
(Retrofit 1.9)
LoginService loginService = RetrofitClient.createService(LoginService.class);
loginService.searchOffer(getToken(), offerSearch, new Callback<String>() {
#Override
public void success(String offerSearchRequestResource, Response response) {
String responseFromSercer = response.getBody();
}
#Override
public void failure(RetrofitError error) {
}
});
change your response model to
JSONObject (from Gson)
then in your
public void success(...){response.body.toString();}
like this:
Call<JsonObject> call = YOUR_API_INTERFACE().YOUR_METHOD(YOUR_PARAMS);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, #NonNull Response<JsonObject> response) {
if(response.isSuccessful()) {
String responseFromSercer = response.body.toString();
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
.....
}
});
If you are sure the request runs successfully and there is a response back...use
System.out.println(response.getBody());
i'd also suggest you add Logging Interceptors here so that you can get a detailed view of all your API calls
I want to get the retrofit response list and use it outside the OnResponse function, but went I try to do it I'm always getting a null object.
Here is my source code
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<ActivitiesResponse> call = apiService.getUserActivities(id);
call.enqueue(new Callback<ActivitiesResponse>() {
// If success
#Override
public void onResponse(Call<ActivitiesResponse>call, Response<ActivitiesResponse> response) {
list = response.body().getActivities();// I'm getting a not null response
}
// If failed
#Override
public void onFailure(Call<ActivitiesResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
//When I try to use the list here I'm getting a null object
Requests are async, so when you try to return a value, the request is likely not done yet so you cannot use it outside of the request. If you want to return values from the request use callback interfaces.
Change your code to a method and pass a callback parameter
Example
public void doRequest(final ApiCallback callback) {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<ActivitiesResponse> call = apiService.getUserActivities(id);
call.enqueue(new Callback<ActivitiesResponse>() {
// If success
#Override
public void onResponse(Call<ActivitiesResponse>call, Response<ActivitiesResponse> response) {
list = response.body().getActivities();
callback.onSuccess(list); // pass the list
}
// If failed
#Override
public void onFailure(Call<ActivitiesResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
public interface ApiCallback{
void onSuccess(ArrayList<YOURTYPE> result);
}
Example usage in onResume(), basically you can do this anywhere you want:
public void onResume(){
super.onResume();
doRequest(new ApiCallback(){
#Override
public void onSuccess(ArrayList<YOURTYPE> result){
//do stuff here with the list from the request
}
});
}
Let me know if this fits your needs
Because onResponse() runs asynchronously. You can not get its value like that.
You should call the method which uses list value inside onResponse().
For example.
call.enqueue(new Callback<ActivitiesResponse>() {
// If success
#Override
public void onResponse(Call<ActivitiesResponse>call, Response<ActivitiesResponse> response) {
list = response.body().getActivities();// I'm getting a not null response
yourMethod();
}
// If failed
#Override
public void onFailure(Call<ActivitiesResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
private void yourMethod() {
// list is used somewhere here
}
I'm using Retrofit 2.0. To get some data from RESTFull services I use procedures like this:
public Call downloadUser() {
// Create RetrofitService
Call<User> call = service.getUser();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
// Do some operations with User obj if response.isSuccess()
}
#Override
public void onFailure(Throwable t) {
// Failure
}
});
return call;
}
In some cases, I need to cancel my request. I use call.cancel(), but even if I call this procedure Callback.onResponse(...) or Callback.onFailure(...) triggered anyway, so using Call.cancel() doesn't cancel my request and it keeps on going until failure or response.
To know if a call was canceled or if it was truly successful you'll need to two a few things.
First it looks like the version of Retrofit2 you are using needs to be updated
Second you can check if a call was canceled based on the code below. Note that this will deal with cancels from the Call<> or the Dispatcher.class in OKHttp3
#Override
public void onResponse(Response<User> response, Response response) {
if(response != null && response.isSuccessful()) {
//Do Stuff with the response
}
}
#Override
public void onFailure(Call<User> user, Throwable t) {
if(user.isCanceled() || "Canceled".equals(t.getMessage())) {
//Call was canceled
} else {
//Call failed
}
}
I need make POST request with parameters "guid=1" in Body. i use Retrofit2
I try :
#POST("/api/1/model")
Call<ApiModelJson> getPostClub(#Body User body);
User Class:
public class User {
#SerializedName("guid")
String guid;
public User(String guid ) {
this.guid = guid;
}
MailActivity:
User user =new User ("1");
Call<ApiModelJson> call = service.getPostClub(user);
call.enqueue(new Callback<ApiModelJson>() {
#Override
public void onResponse(Response<ApiModelJson> response) {
}
#Override
public void onFailure(Throwable t) {
dialog.dismiss();
}
How make this request?
you have to call call.enqueue, providing an instance of Callback< ApiModelJson>, where you will get the response. enqueue executes your backend call asynchronously. You can read more about call.enqueue here
With code below, you can make the request synchronously:
ApiModelJson responseBody = call.execute();
If you want it to be asynchronous:
call.enqueue(new Callback<ApiModelJson>() {
#Override
public void onResponse(Response<ApiModelJson> response, Retrofit retrofit) {
}
#Override
public void onFailure(Throwable t) {
}
});
I am not able to get success response status code from response like 200,201.. etc. As we can easily get error codes from RetrofitError class like error.isNetworkError() and error.getResponse().getStatus(). Is there any workaround for getting status codes?
As per Retrofit 2.0.2, the call is now
#Override
public void onResponse(Call<YourModel> call, Response<YourModel> response) {
if (response.code() == 200) {
// Do awesome stuff
} else {
// Handle other response codes
}
}
Hope it helps someone :-)
EDIT: Many apps could also benefit from just checking for success (response code 200-300) in one clause, and then handling errors in other clauses, as 201 (Created) and 202 (Accepted) would probably lead to the same app logic as 200 in most cases.
#Override
public void onResponse(Call<YourModel> call, Response<YourModel> response) {
if (response.isSuccessful()) {
// Do awesome stuff
} else if (response.code() == 401) {
// Handle unauthorized
} else {
// Handle other responses
}
}
You can get the status code in success() just like you do it in failure()
#Override
public void success(Object object, Response response) {
response.getStatus() // returns status code integer
}
Since you have a Response object in success callback as response.getStatus()
EDIT
I assume you are using okhttp with retrofit.
okhttp has a powerful tool called Interceptor
You can catch the response before retrofits Callback and get status code from the response:
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor(){
#Override
public Response intercept(Chain chain) throws IOException{
Request request = chain.request();
Response response = chain.proceed(request);
response.code()//status code
return response;
});
// then add it to you Restclient like this:
restAdapter = new RestAdapter.Builder()
.setEndpoint(URL_SERVER_ROOT)
.setClient(new OkClient(client)) //plus your configurations
.build();
To learn more about interceptors visit here.
i achieved it by following codes:
public abstract class BaseCallBack<T> {
public abstract void onSuccess(Response<T> response);
public abstract void onFailure(Response<T> response);
}
public abstract class SuccessCallback<T> extends BaseCallBack<T> implements Callback<T>{
#Override
public void onResponse(Call<T> call, Response<T> response) {
if(response.code()>= 400 && response.code() < 599){
onFailure(response);
}
else {
onSuccess(response);
}
}
#Override
public void onFailure(Call<T> call, Throwable t){
}
#Override
public void onSuccess(Response<T> response) {
}
#Override
public void onFailure(Response<T> response) {
}
}
When the rest api returns 400 etc then the onFailure method will be call by default. If you wanna do something onsuccess:(when returns 200 etc)
ServiceConnector.api.getHomePage().enqueue(new SuccessCallback<Void>() {
#Override
public void onSuccess(Response<Void> response) {
super.onSuccess(response);
}
});
you should get exception code iin onError response
HttpException httpException =((HttpException) e).code();