android - implementar - retrofit post
¿Cómo puedo manejar el cuerpo de respuesta vacío con Retrofit 2? (4)
Recientemente comencé a usar
Retrofit 2
y me enfrenté a un problema al analizar el cuerpo de respuesta vacío.
Tengo un servidor que responde solo con código http sin ningún contenido dentro del cuerpo de respuesta.
¿Cómo puedo manejar solo la metainformación sobre la respuesta del servidor (encabezados, código de estado, etc.)?
¡Gracias por adelantado!
Así es como lo usé con Rx2 y Retrofit2, con la solicitud PUT REST: Mi solicitud tenía un cuerpo json pero solo un código de respuesta http con un cuerpo vacío.
El cliente 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;
}
La interfaz:
public interface DevicesEndpoint {
@Headers("Content-Type: application/json")
@PUT(ApiContract.DEVICES_ENDPOINT)
Observable<ResponseBody> sendDeviceDetails(@Body Device device);
}
Luego para usarlo:
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");
}
});
}
Editar:
Como señala Jake Wharton,
@GET("/path/to/get")
Call<Void> getMyData(/* your args here */);
es la mejor manera de ir en comparación con mi respuesta original:
Puede devolver un
ResponseBody
, que omitirá el análisis de la respuesta.
@GET("/path/to/get")
Call<ResponseBody> getMyData(/* your args here */);
Entonces en tu llamada,
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
}
});
Si está utilizando rxjava, use algo como:
@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);
Si usa RxJava, entonces es mejor usar
Completable
en este caso
Representa un cálculo diferido sin ningún valor, sino solo una indicación de finalización o excepción. La clase sigue un patrón de eventos similar al de Reactive-Streams: onSubscribe (onError | onComplete)?
http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Completable.html
en la respuesta aceptada:
@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);
Si el punto final devuelve el código de respuesta de falla, aún estará en
onNext
y tendrá que verificar el código de respuesta usted mismo.
Sin embargo, si usa
Completable
.
@GET("/path/to/get")
Completable getMyData(/* your args here */);
solo tendrá
onComplete
y
onError
.
si el código de respuesta es exitoso, activará
onComplete
contrario, activará
onError
.