How can I handle empty response body with Retrofit 2?

浪子不回头ぞ 提交于 2019-11-27 17:33:37

Edit:

As Jake Wharton points out,

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

is the best way to go versus my original response --

You can just return a ResponseBody, which will bypass parsing the response.

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

Then in your call,

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

If you use RxJava, then it's better to use Completable in this case

Represents a deferred computation without any value but only indication for completion or exception. The class follows a similar event pattern as Reactive-Streams: onSubscribe (onError|onComplete)?

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

in the accepted answer:

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

If the endpoint returns failure response code, it will still be in the onNext and you will have to check the response code yourself.

However, if you use Completable.

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

you will have only onComplete and onError. if the response code is success it will fire the onComplete else it will fire onError.

If you are using rxjava, use something like :

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

Here is how I used it with Rx2 and Retrofit2, with PUT REST request: My request had a json body but just http response code with empty body.

The Api client:

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;

}

The interface:

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

Then to use it:

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

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!