2015-11-16 19 views
12

मैं अपने प्रोजेक्ट में अवलोकन इंटरफेस और परिणाम रैपर के साथ रेट्रोफिट 2 का उपयोग कर रहा हूं। (उदाहरण के हेडर, http स्थिति ... के लिए)रेट्रोफिट 2 और आरएक्सजेवा त्रुटि ऑपरेटिंग ऑपरेटरों

@POST("api/login") 
Observable<Result<LoginResponse>> login(@Body LoginRequest request); 

मैं सिर्फ धारावाहिक वस्तु से प्रतिक्रिया से अधिक जानकारी प्राप्त करने के लिए परिणाम आवरण की जरूरत है: उदाहरण।

समस्या परिणाम आवरण कोई अपवाद नेटवर्क कॉल द्वारा फेंक दिया जाता है के साथ, है। परिणामस्वरूप आतंक() को कॉल करके आप परिणाम के अंदर अपवाद पा सकते हैं।

यदि मैं RxJava त्रुटि ऑपरेटरों का लाभ उठाना चाहता हूं तो मुझे क्या करना चाहिए? उदाहरण के लिए, मैं नेटवर्क त्रुटि पर पुनः प्रयास ऑपरेटर का उपयोग करना चाहता हूं, लेकिन पुनः प्रयास ऑपरेटर केवल तभी काम करता है जब अवलोकन द्वारा अपवाद डाला जाता है।

+0

लिंक को देखें http://bytes.babbel.com/en/articles/2016-03-16-retrofit2-rxjava-error-handling.html वे वर्णन करते हैं कि _Retrofit.Builder_ में _RxJavaCallAdapterFactory_ को ओवरराइड करने के लिए और वहां वहां के लिए आप _Observable.onResumeErrorNext_/_Observable.onDoNext() _ – murt

उत्तर

13

यहां समाधान है जिसके साथ मैं आया था। यदि मैं इसे बेहतर बनाउंगा तो मैं यहां परिवर्तन पोस्ट करूंगा।

मेरी समस्या (अपवाद रेट्रोफिट द्वारा निगल लिया और RxJava द्वारा नियंत्रित नहीं) का हल Observable.error विधि है कि एक नए नमूदार बनाता है कि केवल त्रुटि का उत्सर्जन करता है है, इसलिए मैं अपवाद "rethrow" कर सकते हैं।

मैं हर बाकी कॉल है कि एक retrofit.Result का उत्सर्जन करता है करने के लिए संलग्न करने के लिए एक नमूदार ट्रांसफार्मर बनाया। यह ट्रांसफॉर्मर एक अवलोकन लेता है> और, यदि प्रतिक्रिया में कोई त्रुटि नहीं है, तो इसे एक अवलोकन में बदल देती है>। यदि त्रुटियां हैं तो यह एक पर्यवेक्षक लौटाता है। कस्टम एचटीपी * अपवाद के साथ आतंक जिसे मैं बाद में अपने ऑब्जर्वर में ऑनर कॉलबैक में संभाल सकता हूं। मैं ObservableTransformations.resultToResponseWithHttpErrorHandling नामक एक उपयोगिता वर्ग के एक स्थिर पद्धति के रूप में डाल दिया।

संदेश यह है:

public class ObservableTransformations { 

public static <T> Observable.Transformer<Result<T>, Response<T>> resultToResponseWithHttpErrorHandling() { 
    return observable -> observable.flatMap(r -> { 
     Observable<Response<T>> returnObservable = Observable.just(r.response()); 
     if (r.isError()) { 
      Throwable throwable = r.error(); 
      if (throwable instanceof IOException) { 
       Timber.e(throwable, "Retrofit connection error."); 
       // TODO Check this cases 
       if (throwable instanceof java.net.ConnectException) { 
        returnObservable = Observable.error(new HttpNoInternetConnectionException()); 
       } else if (throwable instanceof SocketTimeoutException) { 
        returnObservable = Observable.error(new HttpServerDownException()); 
       } else { 
        returnObservable = Observable.error(new HttpNoInternetConnectionException()); 
       } 
      } else { 
       Timber.e(throwable, "Retrofit general error - fatal."); 
       returnObservable = Observable.error(new HttpGeneralErrorException(r.error())); 
      } 
     } else { 
      Response<T> retrofitResponse = r.response(); 
      if (!retrofitResponse.isSuccess()) { 
       int code = retrofitResponse.code(); 
       String message = ""; 
       try { 
        message = retrofitResponse.errorBody().string(); 
       } catch (IOException e) { 
        Timber.e(e, "Error reading errorBody from response"); 
       } 
       Timber.i("Server responded with error. Code: " + code + " message: " + message); 
       Throwable t = null; 
       if (NetworkUtils.isClientError(code)) { 
        t = new HttpClientException(retrofitResponse.code(), message); 
       } else if (NetworkUtils.isServerError(code)) { 
        t = new HttpServerErrorException(retrofitResponse.code(), message); 
       } 
       returnObservable = Observable.error(t); 
      } 
     } 
     return returnObservable; 
    }).retryWhen(new RetryWithDelayIf(3, 1000, t -> { 
     return (t instanceof HttpNoInternetConnectionException) || (t instanceof HttpServerDownException); 
    })); 
} 

} 

पुन: प्रयास करें एक घातीय backoff का उपयोग कर 3 बार किया जाता है, और केवल यदि अपवाद HttpNoInternetConnectionException या HttpServerDownException है।

RetryWithDelayIf कक्षा यहां है। कन्स्ट्रक्टर के आखिरी तर्क के रूप में पुनः प्रयास करने के लिए स्थिति को पूरा किया जाता है (एक फंक्शन फेंकने योग्य और सही लौटने पर यदि यह फेंकने योग्य पुनः प्रयास करना चाहिए और गलत नहीं है)।

restService.login(new LoginRestRequest(username, password)) 
       .compose(ObservableTransformations.resultToResponseWithHttpErrorHandling()); 

onError अपने पर्यवेक्षक की में आप अंत में Http * अपवाद संभाल कर सकते हैं:

public class RetryWithDelayIf implements 
    Func1<Observable<? extends Throwable>, Observable<?>> { 

private final int maxRetries; 
private final int retryDelayMillis; 
private int retryCount; 
private Func1<Throwable, Boolean> retryIf; 

public RetryWithDelayIf(final int maxRetries, final int retryDelayMillis, Func1<Throwable, Boolean> retryIf) { 
    this.maxRetries = maxRetries; 
    this.retryDelayMillis = retryDelayMillis; 
    this.retryCount = 0; 
    this.retryIf = retryIf; 
} 

@Override 
public Observable<?> call(Observable<? extends Throwable> attempts) { 
    return attempts.zipWith(Observable.range(1, maxRetries + 1), (n, i) -> { 
     return new Tuple<Throwable, Integer>(n, i); 
    }) 
      .flatMap(
        ni -> { 
         if (retryIf.call(ni.getFirst()) && ni.getSecond() <= maxRetries) { 
          return Observable.timer((long) Math.pow(2, ni.getSecond()), TimeUnit.SECONDS); 
         } else { 
          return Observable.error(ni.getFirst()); 
         } 
        }); 
} 

} 

अंत में, यहाँ एक restService कॉल के साथ उपयोग है।

+0

एक ऐसे समाधान की तरह लग रहा है जो मेरी समस्या के लिए सहायक हो सकता है।कृपया मेरा प्रश्न देखें और शायद हम समुदाय के लाभ के लिए एक अच्छा सामान्य समाधान के साथ आ सकते हैं। http://stackoverflow.com/questions/39437299/rxjava-retrofit-baseobservable-for-api-calls-for-centralized-response-handl – GuyZ

0

आपको यह जांचना चाहिए कि थ्रोबल फेंकने HttpException का एक उदाहरण है या नहीं।

+0

में अपनी ऑब्जेक्ट्स को पकड़ सकते हैं मुझे खेद है लेकिन मुझे लगता है कि आप समस्या को समझ नहीं पाए। वैसे, रेट्रोफिट 2 अब एक सामान्य IOException फेंकता है अगर यह सर्वर तक नहीं पहुंच सकता (कोई इंटरनेट कनेक्शन नहीं, सर्वर नीचे ..)। – Ena

संबंधित मुद्दे