2015-05-13 9 views
5

İletişim için bir Android uygulamasında RxJava ile Retrofit kullanıyorum ve yanıtı tamam yanıt veren HTTP yanıtından (status 200 code) çözümlemede hatayla uğraşmak zorundayım.RxJava retrySonra yayımı yeniden gönderirken

Ayrıca, yeniden deneme yapılıp yapılmayacağına karar vermek için kullanıcının girişine bağlı retryWhen operatörünü kullanarak hatayı işlemenin bir yolunu uygulamış oldum. Bu, özgün Observable'a yeniden göndererek çalışır. Hizmet tekrar çağrılmaz Bununla

services.getSomething() 
    .map(response -> { 
    if (checkBadResponse(response)) { 
     throw new RuntimeException("Error on service"); 
    } else { 
     return parseResponse(response); 
    } 
    }).retryWhen(this::shouldRetry); 

:

denedim ilk yaklaşım

böyle bir şey olması idi. retryWhen operatörünün hizmetin Observable numarasına yeniden abone olamayacağı anlaşılıyor.

ileri onCompleted göndermek ve aşağıdaki gibi lift ile kullanmayan başka operatöre hayata geçiren çalışma sonunda Ne: Kullanılması

public class CheckResponseStatus<T> implements Observable.Operator<ResponsePayload<T>, ResponsePayload<T>> { 
    @Override 
    public Subscriber<? super ResponsePayload<T>> call(Subscriber<? super ResponsePayload<T>> subscriber) { 
     return new Subscriber<ResponsePayload<T>>() { 
      private boolean hasError = false; 

      @Override 
      public void onCompleted() { 
       if (!hasError) 
        subscriber.onCompleted(); 
      } 

      @Override 
      public void onError(Throwable e) { 
       hasError = true; 
       subscriber.onError(e); 
      } 

      @Override 
      public void onNext(ResponsePayload<T> response) { 
       if (response.isOk()) { 
        subscriber.onNext(response); 
       } else { 
        hasError = true; 
        subscriber.onError(new RuntimeException(response.getMessage())); 
       } 
      } 
     }; 
    } 
} 

hoşuna:

services.getSomething() 
    .lift(new CheckResponseStatus()) 
    .map(response -> parseResponse(response)) 
    .retryWhen(this::shouldRetry); 

bu mu Onunla uğraşmanın doğru yolu ya da daha basit, daha iyi bir yolu var mı?

+1

Eğer '.retryWhen' öğesini kaldırırsanız, Gözlemcinizde' onError 'mesajını alıyor musunuz? – Haspemulator

+0

Evet, yapıyorum! Hata normal olarak yayılır. – alcarv

+0

'RetryWhen', kendisine sağlanan işlevin yeniden gönderilmesini nasıl sağlayabileceğinizi anlamanız açısından özellikle zor bir operatördür. Kodundan çözebildiğim, gelenleri göz ardı edemeyeceğinizi ve zincirlemeniz gerektiğini. – akarnokd

cevap

4

rx-java uygulamasında bir hataya benziyor. Her neyse, map fonksiyonundan bir istisna atmak, fonksiyonun saf olması gerektiği için kötü bir şeydir (örneğin yan etkiler olmadan). Eğer durumunda bir flatMap operatörü kullanmalısınız:

services.getSomething() 
    .flatMap(response -> { 
    if (checkBadResponse(response)) { 
     return Observable.<ResponseType>error(new RuntimeException("Error on service")); 
    } else { 
     return Observable.<ResponseType>just(parseResponse(response); 
    } 
    }).retryWhen(this::shouldRetry); 

kod yukarıda beklendiği gibi çalışır ve gerçekten hata oluşursa isteği yeniden dener.

+0

Bu, operatörün "lift" ile kullanmak için uygulanması yerine daha basit bir yoldur. Bunun senaryoda çalışıp çalışmadığını kontrol edeceğim. 'Map'' içinde bir yan etki olarak atmayı gerçekten düşünmedim, sadece RxJava'da uygulanan hatayı tetiklemenin bir yolu, ama bu kesinlikle bir nokta. Bu fikri başka bir sorudan yakaladım. – alcarv

+3

@AndreLuiz 'rxjava' sürümünü kullanıyorsunuz? Bu sorunu github https://github.com/ReactiveX/RxJava/pull/2852 adresinde buldum ve '1.0.9' da düzeltilmiş gibi görünüyor. –

+0

En son RxAndroid 0.24.0 tarafından sağlanan 1.0.4 kullanıyordum. Sadece 1.0.10 ile test edildi ve işe yaradı! Gerçekten bir böcekti. Ve bu arada 'flatMap' kullanan versiyon da 1.0.4'te çalışıyor. Teşekkür ederim! :) – alcarv