2015-10-20 5 views
70

Kürzlich habe ich begonnen, Retrofit 2 zu verwenden, und ich hatte ein Problem mit der Analyse leerer Antworttextkörper. Ich habe einen Server, der nur mit HTTP-Code ohne Inhalt im Antworttext reagiert. Wie kann ich nur Metainformationen über die Serverantwort (Header, Statuscode usw.) verarbeiten?Wie kann ich leere Antwortkörper mit Retrofit 2 behandeln?

Vielen Dank im Voraus!

Antwort

123

Edit:

Als Jake Wharton weist darauf hin,

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

ist der beste Weg, im Vergleich zu meiner ursprünglichen Antwort zu gehen -

Sie können nur ein ResponseBody zurückkehren, das Parsing umgehen wird die Antwort.

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

Dann in Ihren 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 
    } 
}); 
+45

Noch besser: Verwenden Sie 'Void', das nicht nur eine bessere Semantik hat, sondern im leeren Fall (etwas) effizienter und in einem nicht leeren Fall wesentlich effizienter ist (wenn Sie sich einfach nicht um den Körper kümmern). –

+1

@JakeWharton Das ist gutes Benehmen. Danke für das Aufzeigen. Antwort aktualisiert – iagreen

+1

Super! Danke Jungs, funktioniert jetzt –

15

Wenn Sie rxjava verwenden, verwenden Sie so etwas wie:

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

Das ist, was ich gefunden habe! Vielen Dank! – Sirelon

+0

Ich habe ResposeBody mit RxJava2 und Retrofit2 für PUT REST Anforderung verwendet. Es funktionierte gut –

+0

Wir haben eine Endpunkt-API, die leere Stelle bei Erfolg und JSON-Körper, wenn Fehler zurückgegeben. Wie kann ich bei Verwendung der Antwort den Fehlerfall behandeln? –

0

Hier ist, wie ich es mit Rx2 und Retrofit2 verwendet, mit REST PUT Anfrage: Meine Anfrage hatte einen JSON-Körper, sondern nur HTTP-Antwort-Code mit leeren Körper.

Die 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, es zu benutzen:

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

Wenn Sie RxJava verwenden, dann ist es besser Completable in diese verwenden Fall

Repräsentiert eine verzögerte Berechnung ohne irgendeinen Wert, sondern nur eine Anzeige für die Vervollständigung oder 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 akzeptierte Antwort:

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

Wenn der Endpunkt Ausfall Antwortcode zurückgibt, wird es in der onNext sein nach wie vor, und Sie werden den Antwortcode selbst überprüfen müssen.

Wenn Sie jedoch Completable verwenden.

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

Sie nur onComplete und onError haben. Wenn der Response-Code erfolgreich ist, wird die onComplete ausgelöst, andernfalls wird onError ausgelöst.