2016-10-05 11 views
1

Ich benutze Retrofit2 mit Rx. Ich habe zwei API-Aufrufe. Wenn der erste Aufruf eine leere Antwort mit Code 400 zurückgibt, muss ich einen zweiten API-Aufruf machen, wenn nicht, dann nur um das Ergebnis anzuzeigen. Ich habe benutzerdefinierte Fehlerbehandlung implementiert wie gezeigt here. Hier ist meine Lösung:Android Retrofit2 mit rx sequentiellen Anfragen

getResponse1(token) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new ObserverErrorImpl<Response1, BaseError>(BaseError.class) { 
       @Override 
       public void onNext(Response1 response) { 
        view.onSuccess(response); 
       } 

       @Override 
       public void onClientError(BaseError response) { 
        getResponse2(token) 
          .subscribeOn(Schedulers.newThread()) 
          .observeOn(AndroidSchedulers.mainThread()) 
          .subscribe(new ObserverErrorImpl<Response2, BaseError>(BaseError.class) { 

           @Override 
           public void onNext(Response2 response) { 
            view.onSuccess(response); 
            view.hideProgress(); 
           } 

           @Override 
           public void onError(Throwable throwable) { 
            super.onError(throwable); 
            view.hideProgress(); 
           } 
          }); 
       } 

       @Override 
       public void onError(Throwable throwable) { 
        super.onError(throwable); 
        view.hideProgress(); 
       } 
      }); 

Ist es möglich, diesen Code zu vereinfachen, die onClientError innerhalb Methode geht? Ist es eine gute Lösung, das zu mögen?

Antwort

2

1). es zu vereinfachen, wäre es besser, dass Response1 und Response2 werden einige Basisklasse erweitern, so in der Kette, können Sie mit der Basisklasse arbeiten können, die auf bestimmte Art, wenn

benötigt gegossen werden können

Also, nehmen sie an, dass Sie haben BaseResponse:

public abstract class BaseResponse{ 

    public static int TYPE_RESPONSE_1 = 1; 
    public static int TYPE_RESPONSE_2 = 2; 

    public abstract int getType(); //every class MUST override this method 
} 

Response1 und Response2BaseResponse

2) außer Kraft setzen sollte.getResponse1 und getResponse2 sollte Observable<BaseResponse>

3) zurück. Ihr Zielcode:

getResponse1(token) 
      .onErrorResumeNext(new Func1<Throwable, Observable<BaseResponse>>() { 
       @Override 
       public Observable<BaseResponse> call(Throwable throwable) { 
        // I use Retrofit 1.9 
        // And in Retrofit 1.9 I have class RetrofitError, which may provide me all info about error 
        // I'm absolutelly sure Retrofit 2 also have such class, 
        // but it may have another name 
        if(/* is your target error */){ 
         //cast it tour target error 
         return getResponse2(token); 
        } 
        return Observable.error(throwable); 
       } 
      }) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new ObserverErrorImpl<Response1, BaseError>(BaseError.class) { 
       @Override 
       public void onNext(BaseResponse response) { 
        if(response.getType() == BaseResponse.TYPE_RESPONSE_1){ 
         view.onSuccess(response); 
        } else { 
         view.onSuccess(response); 
         view.hideProgress(); 
        } 
       } 

       @Override 
       public void onError(Throwable throwable) { 
        super.onError(throwable); 
        view.hideProgress(); 
       } 
      }); 
0

Jeesh, warum macht es jeder so kompliziert? In der Praxis habe ich das Gefühl, dass ich jedes Mal zu einem Observable im subscribe eines anderen abonnieren benötigt, gibt es ein Bediener, dass es viel mehr sauber für mich tun wird:

<T,E extends Throwable> Observable<T> 
whenExceptionIs(Class<E> what, Func1<E,Observable<T>> result) { 
    return t -> { 
     return what.isInstance(t) ? result.call(t) : Observable.error(t); 
    }; 
} 

getResponse1(token) 
.onErrorResumeNext(whenExceptionIs(BaseError.class, getResponse2(token))) 
.subscribeOn(Schedulers.newThread()) 
.observeOn(AndroidSchedulers.mainThread()) 
.subscribe(view::onSuccess, view::hideProgress, err -> view.hideProgress()); 

Wenn Sie Bedarf spezielle Fehler haben Handhabung erstellen sie eine benutzerdefinierte Subscriber, die die Griffe, aber stellen sie sicher, dass Fehler bei der allgemeinen Handhabung

  • in der Observable Kette behandelt, wenn es etwas darüber (ignorieren, versuchen die Anrufe usw.) tun können
  • propagierten nachgelagerten .
Verwandte Themen