web-dev-qa-db-de.com

Erhalten Sie den Antwortstatuscode mit Retrofit 2.0 und RxJava

Ich versuche, auf Retrofit 2.0 zu aktualisieren und RxJava in mein Projekt Android aufzunehmen. Ich tätige einen API-Aufruf und möchte den Fehlercode im Falle einer Fehlerantwort vom Server abrufen.

Observable<MyResponseObject> apiCall(@Body body);

Und im RxJava-Aufruf:

myRetrofitObject.apiCall(body).subscribe(new Subscriber<MyResponseObject>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(MyResponseObject myResponseObject) {
           //On response from server
        }
    });

In Retrofit 1.9 war der RetrofitError noch vorhanden und wir konnten den Status folgendermaßen abrufen:

error.getResponse().getStatus()

Wie geht das mit Retrofit 2.0 mit RxJava?

98
A.B.

Anstatt den API-Aufruf zu deklarieren, wie Sie es getan haben:

Observable<MyResponseObject> apiCall(@Body body);

Sie können es auch folgendermaßen deklarieren:

Observable<Response<MyResponseObject>> apiCall(@Body body);

Sie haben dann einen Abonnenten wie den folgenden:

new Subscriber<Response<StartupResponse>>() {
    @Override
    public void onCompleted() {}

    @Override
    public void onError(Throwable e) {
        Timber.e(e, "onError: %", e.toString());

        // network errors, e. g. UnknownHostException, will end up here
    }

    @Override
    public void onNext(Response<StartupResponse> startupResponseResponse) {
        Timber.d("onNext: %s", startupResponseResponse.code());

        // HTTP errors, e. g. 404, will end up here!
    }
}

Serverantworten mit einem Fehlercode werden also auch an onNext gesendet, und Sie können den Code durch Aufrufen von reponse.code() abrufen.

http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html

EDIT: OK, ich habe mich endlich mit dem befasst, was e-nouri in ihrem Kommentar gesagt hat, nämlich dass nur 2xx Codes zu onNext. Es stellt sich heraus, dass wir beide Recht haben:

Wenn der Aufruf folgendermaßen deklariert ist:

Observable<Response<MyResponseObject>> apiCall(@Body body);

oder auch das

Observable<Response<ResponseBody>> apiCall(@Body body);

Alle Antworten landen in onNext, unabhängig von ihrem Fehlercode. Dies ist möglich, weil von Retrofit alles in ein Response -Objekt eingeschlossen wird.

Wenn der Aufruf andererseits wie folgt deklariert wird:

Observable<MyResponseObject> apiCall(@Body body);

oder dieses

Observable<ResponseBody> apiCall(@Body body);

in der Tat gehen nur die 2xx Antworten an onNext. Alles andere wird in ein HttpException eingewickelt und an onError gesendet. Was macht auch Sinn, denn ohne den Wrapper Response, was sollte an onNext ausgegeben werden? Da die Anfrage nicht erfolgreich war, wäre es nur sinnvoll, null...

175
david.mihola

Innerhalb der onError-Methode wird der Code abgerufen

((HttpException) e).code()
97
Diveno

Sie sollten beachten, dass ab Retrofit2 alle Antworten mit Code 2xx von onNext () Callback und dem Rest von HTTP-Codes wie 4xx aufgerufen werden, 5xx wird beim onError () Rückruf mit Kotlin aufgerufen. Ich habe mir so etwas in onError () ausgedacht:

mViewReference?.get()?.onMediaFetchFinished(downloadArg)
  if (it is HttpException) {
    val errorCode = it.code()
    mViewReference?.get()?.onMediaFetchFailed(downloadArg,when(errorCode){
      HttpURLConnection.HTTP_NOT_FOUND -> R.string.check_is_private
      else -> ErrorHandler.parseError(it)
    })
  } else {
    mViewReference?.get()?.onMediaFetchFailed(downloadArg, ErrorHandler.parseError(it))
  }
7
MohammadReza