2016-07-05 15 views
0

Ich habe folgendes Szenario. Ich erhalte Daten vom Server mit Retrofit2. Ich möchte Collection<Account> von Account Entitäten herunterladen und für jedes dieser Konten Collection<Project> von Project Entitäten herunterladen. Am Ende möchte ich Map<Account, Collection<Project>> accountsWithProjects bekommen.Transform 2 RxJava Observables auf 1 Karte

Ich habe folgende Methoden:

  1. Observable<Collection<Account>> requestAllAccounts()
  2. Observable<Collection<Project>> requestProjectsInfoForTempoAccount(Account accunt)

Frage: Ist es möglich, irgendwie foreach Iteration dieser beiden reaktiven Ströme zu zip oder erstellen und sammeln Sie alle Einzelteile zur Karte?

Ich kann auch die Sammlung von Projekten für account synchron bekommen, wenn es hilft, kann es jedoch nicht auf Haupt-Thread tun, da die Entwicklung für Android und das Ergebnis auf Haupt-Thread beobachtet werden muss.

Antwort

1

Hier Transform einen besseren Weg:

requestAllAccounts() 
.flatMap(account -> requestProjectsInfoForTempoAccount(account), 
    (acccount, projects) -> Pair::of) 
.toMap(Pair::key, Pair::value); 

(Erweiterung auf Java 7 als Übung für den Leser)

1

Dort haben Sie es:

requestAllAccounts().flatMap(new Func1<Collection<Account>, Observable<Account>>() { 
     @Override 
     public Observable<Account> call(Collection<Account> accountCollection) { 
      return Observable.from(accountCollection); 
     } 
    }).flatMap(new Func1<Account, Observable<Pair<Account, Collection<Project>>>>() { 
     @Override 
     public Observable<Pair<Account, Collection<Project>>> call(Account account) { 
      return Observable.just(account).zipWith(requestProjectsInfoForTempoAccount(account), 
        new Func2<Account, Collection<Project>, Pair<Account, Collection<Project>>>() { 
         @Override 
         public Pair<Account, Collection<Project>> call(Account account, Collection<Project> projects) { 
          return new Pair<Account, Collection<Project>>(account, projects); 
         } 
        }); 
     } 
    }).toList() 
      .flatMap(new Func1<List<Pair<Account, Collection<Project>>>, Observable<Map<Account, Collection<Project>>>>() { 
       @Override 
       public Observable<Map<Account, Collection<Project>>> call(List<Pair<Account, Collection<Project>>> pairs) { 
        Map<Account, Collection<Project>> map = new HashMap<Account, Collection<Project>>(); 
        for (Pair<Account, Collection<Project>> pair : pairs) { 
         map.put(pair.first, pair.second); 
        } 
        return Observable.just(map); 
       } 
      }); 

Was ist hier los?

  1. Erhalten Sie alle Konten.
  2. Split Liste in einzelne Konten
  3. Invoke für Projekte auf einzelne Mailkonto und geben die Pair<Account, Collection<Project>>
  4. Merge alle Objekte
  5. List<Pair<Account, Collection<Project>>>Map<Account, Collection<Project>>
+0

Danke, es gibt nur ein Problem, das ich versuche zu lösen: Die beobachtbare, die Sie erstellt haben, emittiert viele 'Map >' Instanzen. Jede Instanz mit nur einem Map.Entry. Gibt es eine Möglichkeit, sie alle in einer Karte zusammenzufassen, bevor Sie sich anmelden? –

+0

Sind Sie sicher? Wenn die Funktionen 'requestAllAccounts()' und 'requestProjectsInfoForTempoAccount (Account accunt)' die Auflistungen nur einmal zurückgeben (ein 'onNext (...) 'Aufruf), sollte es wie erwartet funktionieren. –

+0

Ja, tut mir leid, du hast Recht. Ich habe versucht, es mit Lambdas neu zu schreiben und etwas zu vermasseln. Danke noch einmal! –