Seit kurzem benutze ich Retrofit 2
und ich hatten ein Problem beim Parsen des leeren Antwortkörpers. Ich habe einen Server, der nur mit http-Code ohne Inhalt im Antworttext antwortet. Wie kann ich nur Metainformationen zur Serverantwort (Header, Statuscode usw.) verarbeiten?
Danke im Voraus!
Bearbeiten:
Wie Jake Wharton betont,
@GET("/path/to/get")
Call<Void> getMyData(/* your args here */);
ist der beste Weg, um gegen meine ursprüngliche Antwort zu gehen -
Sie können einfach ein ResponseBody
zurückgeben, wodurch das Parsen der Antwort umgangen wird.
@GET("/path/to/get")
Call<ResponseBody> getMyData(/* your args here */);
Dann in Ihrem Anruf,
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
}
});
Wenn Sie RxJava verwenden, ist es in diesem Fall besser, Completable
zu verwenden
Stellt eine zurückgestellte Berechnung ohne Wert dar, sondern nur als Hinweis auf den Abschluss oder eine Ausnahme. Die Klasse folgt einem ähnlichen Ereignismuster wie Reactive-Streams: onSubscribe (onError | onComplete)?
http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Completable.html
in der akzeptierten Antwort:
@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);
Wenn der Endpunkt einen Fehlerantwortcode zurückgibt, befindet er sich weiterhin im onNext
, und Sie müssen den Antwortcode selbst überprüfen.
Wenn Sie jedoch Completable
verwenden.
@GET("/path/to/get")
Completable getMyData(/* your args here */);
sie haben nur onComplete
und onError
. Wenn der Antwortcode erfolgreich ist, wird onComplete
ausgelöst, andernfalls onError
.
Wenn Sie rxjava verwenden, verwenden Sie Folgendes:
@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);
Hier ist, wie ich es mit Rx2 und Retrofit2 verwendet habe, mit PUT REST request: Meine Anfrage hatte einen json-Body, aber nur einen http-Antwortcode mit leerem Body.
Der 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;
}
Die Schnittstelle:
public interface DevicesEndpoint {
@Headers("Content-Type: application/json")
@PUT(ApiContract.DEVICES_ENDPOINT)
Observable<ResponseBody> sendDeviceDetails(@Body Device device);
}
Dann benutze es:
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");
}
});
}