RxJava - 将flatMap运算符转发到链中的后续点

时间:2016-03-10 10:00:17

标签: rx-java rx-android

我正在开发一种汽车纸牌游戏,它允许您创建一个帐户并拥有一些汽车卡。基本上,服务器上的每个新创建的帐户都已拥有一些卡。在下面的代码中,我创建了一个帐户,并使用自有车辆的ID将其保存在数据库中。

private Observable<Account> createAccount() {
    return AccountService.createAccount()
            .flatMap(account -> persistAccount(account))
            .flatMap(account -> persistOwnedCarsFromServer(account));
}

private Observable<Account> persistAccount(final Account account) {
    ... persist account ...
    return Observable.just(account);
}

private Observable<Account> persistOwnedCars(final Account account) {
    return AccountService.getOwnedCarIds()
            .flatMap(carIds -> persistOwnedCarIds(account.mId, carIds))
            .flatMap(carsIds -> Observable.just(account)); // don't like this line
}

private Observable<List<Integer>> persistOwnedCarIds(final int accountId, final List<Integer> ownedCarIds){
    ... persist car ids together with accountId ...
    return return Observable.just(ownedCarIds);
}

我对此代码的问题是persistOwnedCars()中的最后一行。我宁愿删除这一行,让方法返回Observable<List<Integer>>作为结果,所以我也可以在其他地方使用它。所以实际上我想在createAccount()方法中实现类似的东西:

private Observable<Account> createAccount() {
    return AccountService.createAccount()
            .flatMap(account -> persistAccount(account)) // returns Observable<Account>
            .flatMap(account -> persistOwnedCarsFromServer(account)) // returns Observable<List<Integer>>
            .magic(carIds -> returnAccountFromAbove()); // returns Observable<Account> 
}

有没有办法以某种方式将flatMap operator的结果转发到链中的后一点?或者是否有更好的方法来实现这一切?谢谢!

3 个答案:

答案 0 :(得分:2)

如评论中所述,您最好的选择是将结果映射回帐户类型,如果您稍后需要帐户和列表,可能需要通过Pair类的帮助:

AccountService.createAccount()
   .flatMap(account -> persistAccount(account))
   .flatMap(account -> 
        persistOwnedCarsFromServer(account).map(v -> Pair.of(account, v)) 
   .flatMap(pair -> processList(pair.second).map(v -> v.first));

答案 1 :(得分:1)

看起来你正在做副作用。我猜想persistX是一个I / O操作,通常被视为副作用。你有没有考虑在这里使用doOnNext?如果您不更改account本身但仅使用此对象中的数据写入数据库,文件或其他任何内容然后返回相同的对象,这可能会对您有所帮助。这可能对persistAccount以及persistOwnedCars都很有用。

AccountService.createAccount()
    .doOnNext(account -> persistAccount(account))
    .doOnNext(account -> persistOwnedCars(account));

private void persistAccount(final Account account) {
    // write to database
    // ...
}

// other methods like persistOwnedCars and persistOwnedCarIds here...

答案 2 :(得分:0)

当我在RxSwift中遇到类似的问题时,我从vzsg得到了这个。

getFoo().flatMap { foo in
    getBars(ofFoo: foo.id).map { bars in (foo, bars) }
}