web-dev-qa-db-ja.com

Retrofit 2.0およびRxJavaを使用して応答ステータスコードを取得する

Retrofit 2.0にアップグレードして、RxJavaをAndroidプロジェクトに追加しようとしています。 API呼び出しを行っており、サーバーからエラー応答があった場合にエラーコードを取得したい。

Observable<MyResponseObject> apiCall(@Body body);

そして、RxJava呼び出しで:

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

Retrofit 1.9では、RetrofitErrorがまだ存在していたため、次の操作を行うことでステータスを取得できました。

error.getResponse().getStatus()

RxJavaを使用してRetrofit 2.0でこれをどのように行いますか?

96
A.B.

あなたがしたようにAPI呼び出しを宣言する代わりに:

Observable<MyResponseObject> apiCall(@Body body);

次のように宣言することもできます。

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

その後、次のようなサブスクライバーが作成されます。

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!
    }
}

したがって、エラーコードを含むサーバーの応答もonNextに配信され、reponse.code()を呼び出すことでコードを取得できます。

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

EDIT:OK、私はついに、e-nouriが彼らのコメントで言ったこと、すなわち2xxコードだけがonNextに対してすることを調べることに回りました。私たちはどちらも正しいことがわかりました:

呼び出しが次のように宣言されている場合:

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

またはこれでさえ

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

all応答は、エラーコードに関係なくonNextになります。これは、すべてがRetrofitによってResponseオブジェクトにラップされているため可能です。

一方、呼び出しが次のように宣言されている場合:

Observable<MyResponseObject> apiCall(@Body body);

またはこれ

Observable<ResponseBody> apiCall(@Body body);

実際、2xx応答のみがonNextに送られます。それ以外はすべてHttpExceptionでラップされ、onErrorに送信されます。また、Responseラッパーがなければ、onNextに何を発行すべきなのかリクエストが成功しなかったことを考えると、送出する唯一の賢明なものはnull...です。

172
david.mihola

これに置かれたonErrorメソッド内でコードを取得

((HttpException) e).code()
93
Diveno

Retrofit2のコードを持つすべての応答2xxがonNext()コールバックから呼び出され、残りのHTTPコードが4xxのように、 5xxはonError()コールバックで呼び出されますKotlinを使用してonError()でこのようなものを思いつきました:

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