当Obs B依赖于Obs A时合并两个可观察量

时间:2017-06-08 11:40:55

标签: android rx-java rx-android

我有两个存储库类,存储库A作为Observable的竞争列表>。

我的竞赛班有一个countryId。

我还有一个存储库B,它返回一个国家列表作为Observable>或Id作为可观察的单个国家

我想要检索我的竞赛列表,并通过返回包含以下内容的CountryCompetition类以某种方式将其与各自的国家合并:

class CountryCompetition {
    public Country country;
    public Competition competition;
}

这意味着将我的competitionService.getCompetitions()countryService.getCountry(competition.id)结合起来,但我不知道如何实现这一目标; mergezip采取观察,我没有每个国家的ID"但是"。

 mCompetitionService.getCompetitions(wrapSearch(constraint))
                .flatMap(new Func1<List<Competition>, Observable<Competition>>() {
                    @Override
                    public Observable<Competition> call(List<Competition> competitions) {
                        return Observable.from(competitions);
                    }
                })

                .map(new Func1<Competition, CountryCompetition>() {
                    @Override
                    public CountryCompetition call(Competition competition) {
                        CountryCompetition c = new CountryCompetition();
                        c.setCompetition(competition);
//Here i would like to set the Country as well, but mCountryService.getCountryById(competition.getCountryId()) returns another observable.
                        return c;
                    }
                })
                .toList()
                .subscribeOn(mSchedulerProvider.io())
                .observeOn(mSchedulerProvider.ui())
                .subscribe(subscriber);

2 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,您有两个列表,并且您希望基本合并它们。您可能会发现我的解决方案很有用:

模型类(为简单起见,不包括构造函数):

class Country {
    String name;
    String id;
}

class Competition {
    String name;
    String countryId;
}

class CountryCompetition {
    public Country country;
    public Competition competition;
}

遵循源Observable定义的虚拟数据:

public Observable<List<Competition>> getCompetitions() {
    ArrayList<Competition> competitions = new ArrayList<>();
    competitions.add(new Competition("First", "id_0"));
    competitions.add(new Competition("Second", "id_1"));
    competitions.add(new Competition("Third", "id_1"));
    competitions.add(new Competition("Fourth", "id_2"));
    competitions.add(new Competition("Fifth", "id_3"));

    return Observable.just(competitions);
}

public Observable<List<Country>> getCountries() {
    ArrayList<Country> competitions = new ArrayList<>();
    competitions.add(new Country("Germany", "id_0"));
    competitions.add(new Country("Czech Republic", "id_1"));
    competitions.add(new Country("Slovakia", "id_2"));
    competitions.add(new Country("Poland", "id_3"));

    return Observable.just(competitions);
}

最后合并逻辑。我希望你熟悉lambdas:

public void fun() {
    Observable.zip( // (1)
            getCompetitions(),
            getCountries(),
            Pair::create)
            .flatMap(pair -> getCompetitionsWithCountries(pair.first, pair.second)) // (2)
            .subscribeOn(Schedulers.immediate())
            .observeOn(Schedulers.immediate())
            .subscribe(countryCompetitions -> {
                for (CountryCompetition countryCompetition : countryCompetitions) {
                    System.out.print(countryCompetition.toString()); // (6)
                }
            });
}

public Observable<List<CountryCompetition>> getCompetitionsWithCountries(List<Competition> competitions, List<Country> countries) {
    return Observable.from(competitions) // (3)
            .map(competition -> {
                Country country = searchForCountry(countries, competition.countryId); // (4)
                return new CountryCompetition(country, competition);
            })
            .toList(); // (5)
}

public Country searchForCountry(List<Country> countries, String countryId) {
    for (Country country : countries) {
        if (country.id.equals(countryId)) {
            return country;
        }
    }

    throw new RuntimeException("Country not found");
}

有趣部分的说明。 :

  1. zip()运算符获取两个observable并生成Pair的结果。在这种情况下,一对两个列表。
  2. flatMap()运算符接受此对并返回类型为Observable<List<CountryCompetition>>
  3. 的新observable
  4. from()运算符会获取Competition个列表,并将每个Competition项分别发送到Rx链。
  5. 现在我们有单一竞争和国家/地区列表,因此我们会根据Country搜索countryId对象。现在我们有CompetitionCountry个对象,我们可以map()将它们添加到新的CountryCompetition对象。
  6. 将所有已发出的CountryCompetition项目打包回列表。
  7. 打印结果。对象countryCompetitions的类型为List<CountryCompetition>

答案 1 :(得分:0)

不是超级复杂:

  public Observable<CountryCompetition> getCountyComps(){
      return getCompetitions()
                 .flatMap(competition ->
                      Observable.zip(
                      Observable.just(competition),
                      getCountry(competition.id)),
                      (comp, country) -> new CountryCompetition(comp, country))
    }