2015-05-13 17 views
5

Tôi đang sử dụng Retrofit với RxJava trong ứng dụng Android để liên lạc và phải xử lý lỗi khi phân tích phản hồi từ phản hồi HTTP có vẻ ok (mã trạng thái 200).RxJava retryKhi đăng ký lại tuyên truyền

Tôi cũng đã triển khai cách xử lý lỗi bằng cách sử dụng toán tử retryWhen được kết nối với đầu vào của người dùng để quyết định có nên thử lại hay không. Điều này hoạt động bằng cách đăng ký lại bản gốc Observable.

Cách tiếp cận đầu tiên tôi đã cố gắng là có một cái gì đó như thế này:

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

Với dịch vụ không được gọi một lần nữa. Có vẻ như nhà điều hành retryWhen không thể đăng ký lại với dịch vụ Observable của dịch vụ.

gì kết thúc làm việc đã được thực hiện một hành mà không gửi onCompleted về phía trước và sử dụng nó với lift như sau:

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

Sử dụng nó như:

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

Là này đúng cách để đối phó với nó hoặc là có một cách đơn giản hơn, tốt hơn?

+1

Nếu bạn xóa '.retryKhi', bạn có nhận' onError' trong Trình theo dõi không? – Haspemulator

+0

Vâng, tôi làm! Lỗi thường được truyền đi. – alcarv

+0

'Thử lạiKhi' là một toán tử đặc biệt khó hiểu vì cách bạn có thể yêu cầu nó hủy đăng ký thông qua chức năng được cung cấp cho nó. Những gì tôi có thể giải mã từ mã của nó là bạn không thể bỏ qua các quan sát đến và bạn phải chuỗi qua nó. – akarnokd

Trả lời

4

Dường như lỗi trong việc triển khai rx-java. Dù sao, việc ném một ngoại lệ từ hàm map là một điều xấu vì hàm này được cho là thuần túy (ví dụ như không có tác dụng phụ). Bạn nên sử dụng một nhà điều hành flatMap trong trường hợp của bạn:

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

Đoạn mã trên làm việc như mong đợi và thực sự lại yêu cầu nếu lỗi xảy ra.

+0

Đây thực sự là một cách đơn giản hơn thay vì thực hiện toán tử để sử dụng với 'lift'. Tôi sẽ kiểm tra xem điều này có hiệu quả trong kịch bản của tôi hay không. Tôi thực sự không nghĩ đến việc ném bên trong 'map' là một tác dụng phụ, chỉ là cách kích hoạt lỗi đã được thực hiện trên RxJava, nhưng đó chắc chắn là một điểm. Tôi bắt được ý tưởng này từ một số câu hỏi khác. – alcarv

+3

@AndreLuiz Bạn sử dụng phiên bản 'rxjava' nào? Tôi vừa tìm thấy vấn đề này trên github https://github.com/ReactiveX/RxJava/pull/2852 và có vẻ như nó đã được sửa trong '1.0.9'. –

+0

Tôi đã sử dụng 1.0.4, được bao gồm bởi RxAndroid 0.24.0 mới nhất. Chỉ cần thử nghiệm với 1.0.10 và nó đã làm việc! Nó thực sự là một lỗi. Và bằng cách sử dụng phiên bản 'flatMap' cũng hoạt động trên 1.0.4. Cảm ơn bạn! :) – alcarv

Các vấn đề liên quan