Retrofit 2で空の応答本文を処理するにはどうすればよいですか?


125

最近、Retrofit 2の使用を開始し、空の応答本文の解析に関する問題に直面しました。応答本文内にコンテンツがなく、httpコードでのみ応答するサーバーがあります。

サーバーの応答に関するメタ情報(ヘッダー、ステータスコードなど)のみをどのように処理できますか?

回答:


216

編集:

ジェイクウォートンが指摘するように

@GET("/path/to/get")
Call<Void> getMyData(/* your args here */);

私の元の応答と比較して、最善の方法です-

単にを返すことができResponseBodyます。これにより、応答の解析がバイパスされます。

@GET("/path/to/get")
Call<ResponseBody> getMyData(/* your args here */);

その後、あなたの電話で、

Call<ResponseBody> dataCall = myApi.getMyData();
dataCall.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Response<ResponseBody> response) {
        // use response.code, response.headers, etc.
    }

    @Override
    public void onFailure(Throwable t) {
        // handle failure
    }
});

58
さらに良い:Voidセマンティクスが向上しているだけでなく、空の場合は(わずかに)より効率的であり、空ではない場合(ボディに関心がない場合)は非常に効率的です。
Jake Wharton、

1
@JakeWhartonそれは素晴らしい行動です。指摘してくれてありがとう。回答を更新しました。
iagreen 2015年

2
すばらしい答えです。Voidを使用しない理由の1つは、リクエストが失敗した場合にのみ本文を返すリソースがあり、errorBody ResponseBodyを特定のタイプまたは一般的なタイプに変換する場合です。

7
@JakeWharton使用するための素晴らしい提案VoidUnitKotlinコードでの使用はVoid、Java for Retrofit と同じ利点をもたらしますか?
Akshay Chordiya 2017

6
@ akshay-chordiya私がチェックしたところ、UnitKotlinでは機能しませんが、Void機能します。どこかにハードコードされたチェックがあると思います。
user3363866 2018

40

RxJavaを使用Completableする場合は、この場合に使用することをお勧めします

値のない遅延計算を表しますが、完了または例外を示すだけです。このクラスは、Reactive-Streamsと同様のイベントパターンに従います。onSubscribe(onError | onComplete)?

http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Completable.html

受け入れられた答え:

@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);

エンドポイントが失敗の応答コードを返した場合、それはまだにありonNext、応答コードを自分で確認する必要があります。

ただし、を使用する場合Completable

@GET("/path/to/get")
Completable getMyData(/* your args here */);

とのみにonCompleteなりonErrorます。応答コードが成功した場合は、onCompleteそれ以外の場合は実行されonErrorます。


1
onError Throwableその場合、議論には何が含まれますか?私はこの方がきれいだと思いますが、それでも多くの場合、失敗の応答コードと本文を調べる必要があります。
big_m

24

rxjavaを使用している場合は、次のようなものを使用します。

@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);

それが私が見つけていたものです!ありがとう!
サイレロン2017

ResposeBodyをRxJava2とRetrofit2でPUT RESTリクエストに使用しました。それはうまく
いきました

1
成功した場合は空のボディを返し、エラーの場合はjsonボディを返すエンドポイントAPIがあります。Response <Void>を使用している場合、エラーケースをどのように処理できますか?
KeNVin Favo 2018

ここでどのResponseクラスを使用しますか?レトロフィットまたはOKHttps?
Matthias

1
例外でエラー処理を行う場合、これは良いオプションではありません。このアプローチでは例外は発生しませんが、エラーに対する応答としてJSONが返されます
Ovi Trif

0

PUT RESTリクエストでRx2とRetrofit2を使用する方法は次のとおりです。リクエストにはjsonボディがありましたが、ボディが空のhttp応答コードしかありませんでした。

APIクライアント:

public class ApiClient {
public static final String TAG = ApiClient.class.getSimpleName();


private DevicesEndpoint apiEndpointInterface;

public DevicesEndpoint getApiService() {


    Gson gson = new GsonBuilder()
            .setLenient()
            .create();


    OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    okHttpClientBuilder.addInterceptor(logging);

    OkHttpClient okHttpClient = okHttpClientBuilder.build();

    apiEndpointInterface = new Retrofit.Builder()
            .baseUrl(ApiContract.DEVICES_REST_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
            .create(DevicesEndpoint.class);

    return apiEndpointInterface;

}

インターフェース:

public interface DevicesEndpoint {
 @Headers("Content-Type: application/json")
 @PUT(ApiContract.DEVICES_ENDPOINT)
 Observable<ResponseBody> sendDeviceDetails(@Body Device device);
}

それを使用するには:

    private void sendDeviceId(Device device){

    ApiClient client = new ApiClient();
    DevicesEndpoint apiService = client.getApiService();
    Observable<ResponseBody> call = apiService.sendDeviceDetails(device);

    Log.i(TAG, "sendDeviceId: about to send device ID");
    call.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<ResponseBody>() {
        @Override
        public void onSubscribe(Disposable disposable) {
        }

        @Override
        public void onNext(ResponseBody body) {
            Log.i(TAG, "onNext");
        }

        @Override
        public void onError(Throwable t) {
            Log.e(TAG, "onError: ", t);

        }

        @Override
        public void onComplete() {
            Log.i(TAG, "onCompleted: sent device ID done");
        }
    });

}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.