Retrofit 2 ile boş yanıt gövdesini nasıl idare edebilirim?


125

Son zamanlarda Retrofit 2 kullanmaya başladım ve boş yanıt gövdesini ayrıştırırken bir sorunla karşılaştım. Yanıt gövdesinde herhangi bir içerik olmadan yalnızca http koduyla yanıt veren bir sunucum var.

Yalnızca sunucu yanıtıyla ilgili meta bilgileri (başlıklar, durum kodu vb.) Nasıl işleyebilirim?

Yanıtlar:


216

Düzenle:

Jake Wharton'ın işaret ettiği gibi,

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

benim orijinal cevabıma karşı gitmenin en iyi yolu -

ResponseBodyYanıtı ayrıştırmayı atlayacak bir a döndürebilirsiniz .

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

Sonra aramanızda

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

58
Daha da iyisi: Daha iyi Voidanlambilimine sahip olmakla kalmayıp, boş durumda (biraz) daha verimli ve boş olmayan bir durumda (bedene aldırış etmediğinizde) çok daha verimli olan kullanın.
Jake Wharton

1
@JakeWharton Bu harika bir davranış. Gösterdiğiniz için teşekkürler. Cevap güncellendi.
iagreen

2
Mükemmel cevap. Void'i kullanmamanın bir nedeni, yalnızca istek başarısız olduğunda bir gövde döndüren bir kaynağınız olması ve errorBody ResponseBody'yi belirli veya yaygın bir türe dönüştürmek istemenizdir.

7
@JakeWharton Kullanmak için harika bir öneri Void. UnitKotlin kodunda kullanmak , VoidRetrofit için Java ile aynı faydayı sağlar mı?
Akshay Chordiya

6
@ akshay-chordiya Az önce kontrol ettim, Kotlin'de Unitçalışmıyor, Voidancak çalışıyor. Bir yerde kodlanmış bir çek olduğunu varsayıyorum.
user3363866

41

RxJava kullanıyorsanız Completable, bu durumda kullanmak daha iyidir

Herhangi bir değer içermeyen, ancak yalnızca tamamlanma veya istisna göstergesi olmayan ertelenmiş bir hesaplamayı temsil eder. Sınıf, Reaktif Akışlar ile benzer bir olay modelini izler: onSubscribe (onError | onComplete)?

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

kabul edilen cevapta:

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

Uç nokta hata yanıt kodunu döndürürse, yine de onNext olacaktır ve yanıt kodunu kendiniz kontrol etmeniz gerekecektir.

Ancak, kullanırsanız Completable.

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

sadece onCompleteve olacaksın onError. cevap kodu başarılıysa, ateşlenecekse onCompleteateşlenecektir onError.


1
onError ThrowableBu durumda argüman ne içerecek? Bunu daha temiz buluyorum, ancak yine de arızalar için yanıt koduna ve gövdeye bakmamız gerekiyor.
big_m

24

Rxjava kullanıyorsanız, aşağıdaki gibi bir şey kullanın:

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

Ben de bunu buluyordum! Teşekkürler!
Sirelon

PUT REST isteği için ResposeBody'yi RxJava2 ve Retrofit2 ile kullandım. İyi çalıştı
Moti Bartov

1
Başarılı olduğunda boş gövde ve hata olduğunda json gövdesi döndüren bir uç nokta API'miz var. Response <Void> kullanılıyorsa, hata durumunu nasıl idare edebilirim?
KeNVin Favo

Burada hangi Response sınıfını kullanıyorsunuz? Güçlendirme veya OKHttps?
Matthias

1
İstisnalarda hata işleme yaparsanız bu iyi bir seçenek değildir .. Bu yaklaşımda bir istisna olmaz, bunun yerine hata durumunda yanıt olarak bir JSON elde
edersiniz

0

Bunu Rx2 ve Retrofit2 ile PUT REST isteği ile nasıl kullandım: İsteğimin bir json gövdesi vardı, ancak sadece boş gövdeli http yanıt kodu vardı.

Api istemcisi:

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;

}

Arayüz:

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

Sonra kullanmak için:

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

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.