2015-05-15 16 views
26

2 ağ çağrısını birbiri ardına yürütmek istiyorum. Her iki ağ çağrısı da Gözlenebilir. İkinci çağrı, ilk aramanın başarılı sonucundan veri kullanır, ikinci aramanın başarılı sonucundaki yöntemde, numaralı telefonun verileri numaralı telefonun ilk ve ikinci çağrısının başarılı sonucudur. Ayrıca hem onError "olayları" farklı şekilde ele alabilmeliyim. Ben aşağıdaki örnekte olduğu gibi bu kaçınarak geri arama cehennem elde edebilirsiniz Nasıl:Zinciri iki retrofit gözle görülür zincirleme w/RxJava

 API().auth(email, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Action1<AuthResponse>() { 
       @Override 
       public void call(final AuthResponse authResponse) { 
        API().getUser(authResponse.getAccessToken()) 
          .subscribe(new Action1<List<User>>() { 
           @Override 
           public void call(List<User> users) { 
            doSomething(authResponse, users); 
           } 
          }, new Action1<Throwable>() { 
           @Override 
           public void call(Throwable throwable) { 
            onErrorGetUser(); 
           } 
          }); 
       } 
      }, new Action1<Throwable>() { 
       @Override 
       public void call(Throwable throwable) { 
        onErrorAuth(); 
       } 
      }); 

Ben zip bilmem ama ben için "Birleştirici sınıfı" oluşturarak kaçınmak istiyorum. 1.

Güncelleme akarnokd cevabını uygulamaya çalıştı:

  API() 
      .auth(email, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .flatMap(authResponse -> API() 
        .getUser(authResponse.getAccessToken()) 
        .doOnError(throwable -> { 
         getView().setError(processFail(throwable)); 
        }), ((authResponse, users) -> { 
       // Ensure returned user is the which was authenticated 
       if (authResponse.getUserId().equals(users.get(0).getId())) { 
        SessionManager.getInstance().initSession(email, password, authResponse.getAccessToken(), users.get(0)); 
        getView().toNews(); 
       } else { 
        getView().setError(R.string.something_went_wrong); 
       } 
      })); 

Ancak flatMap içindeki yöntem derleyici o authResponse ve kullanıcılara (authResponse.getAccessToken(), users.get(0) vs.) yöntemlerini çözemezse söylüyor. Rx programlama ve lambdas için yeni - lütfen sorunun ne olduğunu söyle. Neyse kod şimdi daha temiz görünüyor.

Güncelleme 2.

API() 
      .auth(email, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .doOnError(throwable -> getView().setError(processFail(throwable))) 
      .flatMap((AuthResponse authResponse) -> API() 
        .getUser(authResponse.getAccessToken()) 
        .doOnError(throwable -> getView().setError(processFail(throwable))), ((AuthResponse authResponse, List<User> users) -> { 
          // Ensure returned user is the which was authenticated 
          if (authResponse.getUserId().equals(users.get(0).getId())) { 
           SessionManager.getInstance().initSession(email, password, authResponse.getAccessToken(), users.get(0)); 
           getView().toNews(); 
          } 
          return Observable.just(this); 
      })); 

böyle yaptın mı, ama şimdi benim ağ aramaları hiç yürütme değildir.

+0

uzakta bir IDE değilim, ama hata lambda parametre adı çatışma nedeniyle olduğunu düşünüyorum . – akarnokd

+1

Artık abone olmadığınız anlaşılıyor. Zincirin alt tarafındaki .subscribe() öğesini seçtiğinizden emin olun. –

cevap

10

, sizin için birincil ve düzleştirilmiş değerleri bir FUNC2 ve çiftleri götüren bir flatMap aşırı yük vardır. Buna ek olarak, onErrorXXX ve hata manipülasyon için onExceptionXXX operatörleri bakmak ve ilk ve ikinci Gözlenebilirler ile zincirleyin

first.onErrorReturn(1) 
.flatMap(v -> service(v).onErrorReturn(2), (a, b) -> a + b); 
+0

Teşekkürler, bunu deneyeceğim. Android için Retrolambda kullanarak herhangi bir sınırlama var mı? – localhost

+0

Evet, örneğim flatMap() 'ın aşırı yüklenmesini kullanıyordu. onErrorReturn işe yarayabilir ve sadece null döndürür, ancak flatMap() 'deki func, ikinci Gözlemlenebilir'i geri göndermeden önce boş bir kontrole sahip olmalıydı, bence. Bunların hiçbirinin sorudaki orijinal koddan daha açık olacağından emin değilim. –

+0

Ve Android'de retrolambda kullanarak sınırlamalar burada belgelenmiştir: https://github.com/evant/gradle-retrolambda#known-issues –

15

FlatMap()? Eğer (veya zip()) 'e olan ilginiz, sadece iki nesneyi tutmak için gereksiz bir sınıf yapma gereğidir, android.util.Pair bir cevap olabilir. Yine de tam olarak aradığınız hata işleme yöntemini nasıl alacağımı bilmiyorum. Anthony R. cevabı ek olarak

 API().auth(email, password) 
     .subscribeOn(Schedulers.newThread()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .flatMap(new Func1<AuthResponse, Observable<List<User>>>() { 
      @Override 
      public Observable<List<User>> call(AuthResponse authResponse) { 
      return API().getUser(authResponse.getAccessToken()); 
      } 
     }, new Func2<AuthResponse, List<User>, Pair<AuthResponse, List<User>>>() { 
      @Override 
      public Pair<AuthResponse, List<User>> call(AuthResponse authResponse, List<User> users) { 
      return new Pair<>(authResponse, users); 
      } 
     }).subscribe(new Action1<Pair<AuthResponse, List<User>>>() { 
      @Override 
      public void call(Pair<AuthResponse, List<User>> pair) { 
      doSomething(pair.first, pair.second); 
      } 
     }, new Action1<Throwable>() { 
      @Override 
      public void call(Throwable throwable) { 
      // not sure how to tell which one threw the error 
      } 
     }); 
+0

Flatmap ile bana bir örnek verebilir misiniz? Çift için, eğer 2'den fazla nesne varsa? – localhost

+0

Func1'i Func9'da kullanabilirsiniz, ayrıca bir FuncN var. – Aegis

+0

Bu durumda 'API(). GetUser (..)' çağrısı arka plan iş parçacığında çalışmayacak mı? – clu