I am using Retrofit 2.1.0 library, and use call.enqueue method to do async API calls.
The CallBack class returns onResponse(Call call, Response response) and onFailure (Call call, Throwable t).
My question is that, is it safe to assume that the Response ( not response.body) object in the onResponse method will always be NonNull?
If it can be null, what can be the possible scenarios?
I looked online and on Retrofit docs, but no clear answers.
It shouldn't be null.
You can see in Retrofit source code that you only get a Response.success or a Reponse.error returned.
You can check if the HTTP request was a success using Response.isSuccessful().
If the Response was possible to be null, then that method would throw a NullPointerException.
If there was a scenario for a null Response, or some exception thrown when parsing the response, then onFailure would be entered.
Related
I'm using Volley to call api but it always returns "Failed" String in the onResponse method.
I checked the request object and response object and they are the same in postman, post man returns result but volley return "Failed".
Here's the call in fragment
And the call using volley
I am making a POST request using Retrofit, call executes successfully on rest client. Also onResponse of call executes but in response body i am getting error
'unicode' object has no attribute 'items'.
What is the reason of this error?
On android, I make server calls through retrofit and the server can sometimes return a 500 response.
Is there a reason why onError does not get invoked in the subscriber?
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response<Void>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
if (isViewAttached()) {
getView().onError(e);
}
}
#Override
public void onNext(Response<Void> response) {
response.code() <-- why would 500 here not get routed to the onError instead?
}
});
This depends part on your configuration and part on how you defined your call, but it will all boil down to one of 2 Observables.
If you look at the source code you can see that if your call returns a type of Response<Foo> Retrofit will internally create either a CallEnqueueObservable<Foo> or CallExecuteObservable for your call. Check it out in the adapt method. For RxJava 1 this is similar, but the observables are called differently. Anyway, internally the way things work are quite the same. The call is executed and onNext is called with a response instance.
If you take a look at how this works inside Retrofit's proxy mechanism, there will always be a response instance even if the response is an Http error. This means that calling onNext will still happen even if the response is an http error itself. You can have a look at the parseReponse method and as you see there's no exception thrown if the status code is 500.
Back to the observables, only when there's an exception will the subscriber's onError be called. Remember, if it's status code 500 there's no exception thrown.
To get your onError to fire for non 2XX http error codes there are different ways, but one possible way is to (if you can afford it) make your call return Observable<Foo> instead of Observable<Response<Foo>>.
This will make retrofit use internally different observables that will make sure to call your subscriber's onError when there's an http error as well as exceptions.
Only network errorsare thrown into onError (e.g. no internet connection).
Think of a 500er as a valid response from the server instead of an error case. Furthermore you want to use the error information the server provided (Body, status code, Headers, etc.). onError can't provide this (unless as an Exception).
I'm using Retrofit to get some data from a server. The problem is the response body is null (although I get a response code : 200 ) and if you check this github issue like I did you will see that they suggest you to use Call<Void> for empty response's body.
I did change it to Call<Void> and now when I'm making a request with Retrofit it enters onResponse and response is successful, but then I can't deserialize it with Gson.
Using :
DataServiceResponse serviceResponse = gson.fromJson(response.body(), DataServiceResponse.class);
is not possible since response.body() is void.
In my API server returns HTTP 400 response code if request does not pass validation, and provides detailed message, that should be parsed as the response.
For example:
public class RegistrationResponse {
private String emailError; // Detailed message. Null if no error occured
}
But Robospice (Retrofit + OkHttp) fires onRequestFailure() with message "retrofit.RetrofitError: 400 BAD REQUEST" in this case and, of course, does not parse anything.
How should I make it parse the response in case if response code is not 2XX?
You should declare Retrofit methods that return HTTP Response objects and check the raw object in your loadDataFromNetwork() for the status you need. This way, however, you will skip the out-of-the-box functionality of parsing responses and will have to do that manually.
Therefore, you should also find a way to reuse the Converter passed to your RestAdapter in the RetrofitSpiceService. Overriding the RetrofitSpiceService#createConverter() method is probably the simplest way to achieve this.