2016-07-05 48 views
0

我有以下場景。我使用Retrofit2從服務器獲取數據。 我想下載Collection<Account>Account實體,並且對於這些賬戶中的每一個來說,下載Project實體的Collection<Project>。最後我想得到Map<Account, Collection<Project>> accountsWithProjects將2個RxJava Observables轉換爲1個地圖

我有以下幾種方法:

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

問:是否可以壓縮或創建這兩個反應流的莫名其妙的foreach迭代,並收集所有的項目到地圖?

如果有幫助,我也可以同步獲取帳戶項目的集合,但無法在主線程上完成,因爲爲Android開發並且必須在主線程上觀察結果。

回答

1

這裏有一個更好的辦法:

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

(擴展到Java 7作爲excercise for the reader)

1

有你有它:

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); 
       } 
      }); 

這到底是怎麼回事?

  1. 獲取所有帳戶。
  2. 拆分列表爲單一賬戶
  3. 調用搜索在單一賬戶項目,並返回Pair<Account, Collection<Project>>
  4. 合併的所有對象
  5. 變換List<Pair<Account, Collection<Project>>>Map<Account, Collection<Project>>
+0

謝謝,我只想解決一個問題:你創建的observable發出了許多'Map >'實例。每個實例只有一個Map.Entry。訂閱前有沒有辦法將它們全部合併到一個Map中? –

+0

你確定嗎?如果函數requestAllAccounts()和requestProjectsInfoForTempoAccount(Account accunt)只返回集合一次(一個onNext(...)調用),它應該按預期工作。 –

+0

是的,對不起,你說得對。我試圖用lambda表達式重寫它,並搞砸了一些東西。再次感謝! –