2015-11-28 16 views
16

RxJava ve Retrofit için oldukça yeni ve API çağrılarımı yazmaya çalışıyorum. Tüm API çağrıları, genel formatında hata JSON vücudu döndürmek Retrofit 2.0 + RxJava + Hata JSON body

{"errors":[{"code":100, "message":"Login/Password not valid", "arguments":null}]} 

anda giriş API çağrısı (diğerleri de benzer) 'dir benim kod,

mConnect.login(id, password) 
     .subscribe(new Subscriber<Token>() { 
      @Override 
      public void onCompleted() { 
       Log.d(TAG, "onCompleted()"); 
      } 

      @Override 
      public void onError(Throwable e) { 
       Log.e(TAG, "onError(): " + e); 
       if (e instanceof HttpException) { 
        // dump e.response().errorBody() 
       } 
      } 

      @Override 
      public void onNext(Token token) { 
       Log.d(TAG, "onNext(): " + token); 
      } 
     }); 

zaman onError() 'da bir hata olsun, JSON'u hata gövdesinde otomatik olarak bir POJO'ya çözmek istiyorum ve bunu kullanıyorum. Diğer tüm API çağrıları için tercihen tek bir yerde bunu yapmanın bir yolu var. Herhangi bir yardım takdir edilir.

cevap

5

Mantığınızı kapsüllemek için yeniden kullanılabilir Transformer ve onErrorResumeNext operatörünün kullanılmasını öneririm. Eğer çözümlenen yanıtı onError() veya OnNext() bildirmek isteyip istemediğiniz karar vermek zorunda çünkü kodda yorumlarına

<T> Observable.Transformer<T, T> parseHttpErrors() { 
    return new Observable.Transformer<T, T>() { 
     @Override 
     public Observable<T> call(Observable<T> observable) { 
      return observable.onErrorResumeNext(new Func1<Throwable, Observable<? extends T>>() { 
       @Override 
       public Observable<? extends T> call(Throwable throwable) { 
        if (throwable instanceof HttpException) { 
         HttpErrorPojo errorPojo = // deserialize throwable.response().errorBody(); 

         // Here you have two options, one is report this pojo back as error (onError() will be called), 
         return Observable.error(errorPojo); // in this case HttpErrorPojo would need to inherit from Throwable 

         // or report this pojo back as part of onNext() 
         return Observable.just(errorPojo); //in this case HttpErrorPojo would need to inherit from <T> 
        } 
        // if not the kind we're interested in, then just report the same error to onError() 
        return Observable.error(throwable); 
       } 
      }); 
     } 
    }; 
} 

dikkat edin: Böyle bir şey olmazdı.

Sonra böyle API çağrıları herhangi bir yerinde bu trafosu kullanabilirsiniz:

mConnect.login(id, password) 
     .compose(this.<Token>parseHttpErrors()) // <-- HERE 
     .subscribe(new Subscriber<Token>() { 
      @Override 
      public void onCompleted() { 
       Log.d(TAG, "onCompleted()"); 
      } 

      @Override 
      public void onError(Throwable e) { 
       Log.e(TAG, "onError(): " + e); 
       if (e instanceof HttpErrorPojo) { 
        // this will be called if errorPojo was reported via Observable.error() 
       } 
      } 

      @Override 
      public void onNext(Token token) { 
       Log.d(TAG, "onNext(): " + token); 
       if (token instanceof HttpErrorPojo) { 
        // this will be called if errorPojo was reported via Observable.just() 
       } 
      } 
     }); 
0

Deserialize çok bir sorun olabilir. retrofit converter to deserialize it'u kullanabilirsiniz (veya kendiniz yapın).

Çözümümün murki den birine biraz ekler: OnError() daha sonra

<T> Observable.Transformer<T, T> parseHttpErrors() { 
     return new Observable.Transformer<T, T>() { 
      @Override 
      public Observable<T> call(Observable<T> observable) { 
       return observable.onErrorResumeNext(new Func1<Throwable, Observable<? extends T>>() { 
        @Override 
        public Observable<? extends T> call(Throwable throwable) { 
         if (throwable instanceof HttpException) { 
          Retrofit retrofit = new Retrofit.Builder() 
            .baseUrl(SERVER_URL) // write your url here 
            .addConverterFactory(GsonConverterFactory.create()) 
            .build(); 
          Converter<ResponseBody, Error> errorConverter = 
            retrofit.responseBodyConverter(Error.class, new Annotation[0]); 
          // Convert the error body into our Error type. 
          try { 
           Error error = errorConverter.convert(((HttpException) throwable).response().errorBody()); 
           // Here you have two options, one is report this pojo back as error (onError() will be called), 
           return Observable.error(new Throwable(error.getMessage())); 
          } 
          catch (Exception e2) { 
           return Observable.error(new Throwable()); 
          } 

         } 
         // if not the kind we're interested in, then just report the same error to onError() 
         return Observable.error(throwable); 
        } 
       }); 
      } 
     }; 
    } 

ve

@Override 
public void onError(Throwable e) { 
    progressBar.setVisibility(View.GONE); // optional 
    if (!TextUtils.isEmpty(e.getMessage())) { 
      // show error as you like 
      return; 
    } 
    // show a default error if you wish 
}