2015-10-20 1 views
70

Недавно я начал использовать Retrofit 2 и столкнулся с проблемой разбора пустого тела ответа. У меня есть сервер, который отвечает только http-кодом без какого-либо содержимого внутри тела ответа. Как я могу обрабатывать только метаинформацию о ответе сервера (заголовки, код состояния и т. Д.)?Как я могу обработать пустой корпус ответа с помощью Retrofit 2?

Заранее благодарен!

ответ

123

Edit:

Как Jake Wharton указывает,

@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 
    } 
}); 
+45

Еще лучше: используйте «Void», который не только обладает лучшей семантикой, но (в некоторой степени) более эффективен в пустом случае и значительно более эффективен в непустом случае (когда вас просто не волнует тело). –

+1

@JakeWharton Это отличное поведение. Спасибо, что указали это. Ответ обновлен. – iagreen

+1

Удивительный! Спасибо, ребята, сейчас работает –

15

Если вы используете rxjava, использовать что-то вроде:

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

Вот что я нашел! Благодаря! – Sirelon

+0

Я использовал ResposeBody с RxJava2 и Retrofit2 для запроса PUT REST. Он работал нормально –

+0

У нас есть API конечной точки, который возвращает пустое тело при успешном завершении и тело json при ошибке. Если вы используете Response , как я могу обработать ошибку? –

0

Вот как я использовал его с Прм2 и ​​Retrofit2 с PUT ОСТАЛЬНЫХ request: У моего запроса было тело json, но только код ответа HTTP с пустым телом.

АНИ клиент:

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

} 
10

Если вы используете 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.

Смежные вопросы