Rxjava在从数据库中检索然后更新项目时创建一个循环

时间:2018-08-15 16:03:24

标签: java android kotlin

我在使用rxjava时遇到了挑战,可以观察到从数据库中检索项目。我订阅了这个可观察的内容,并成功从数据库中检索了一个项目,然后更新了该项目。问题是在更新项目后立即发生,我观察到的获取项目开始发出,并且再次调用了update方法,从而创建了一个循环。

示例代码

mOrderRepository.getOrder(orderId)
 .subscribeOn(mSchedulerProvider.io())
 .observeOn(mSchedulerProvider.ui())
 .subscribe((Order order) -> {
 // i calculate amount due after payment then update this order
    order.setAmountDue(amountDue);
    mOrderRepository.updateOrder(order);
});

2 个答案:

答案 0 :(得分:0)

如果getOrder(orderId)返回一个Flowable<Order>,它将在每次更新时一次又一次地收到订单,则应在一个单独的Single的上下文中执行该命令,该更新可用于更新给定orderId的项目。

public static final Object UNIT = new Object(); // avoid emitting `null`

public void updateOrder(final long orderId, final long amountDue) {
    Single.fromCallable(() -> UNIT)
            .subscribeOn(Schedulers.io())
            .flatMap((ignored) -> getOrder(orderId).firstOrError()) // <-- convert Flowable to Single
            .doOnSuccess(order -> {
                order.setAmountDue(amountDue);
                mOrderRepository.updateOrder(order);
            }).subscribe();
}

或类似的东西。

答案 1 :(得分:0)

如果每次在数据库中更新Order对象,并且每次在数据库中更新该Order对象时,都会无限循环。缺少的逻辑应该回答以下问题:什么时候不应该更新对象?

一种解决方案,如@akarnokd所建议的,通过指定take(1)将检索限制在第一个发出的项目上:

mOrderRepository.getOrder(orderId)
 .take(1)
 .subscribeOn(mSchedulerProvider.io())
 .observeOn(mSchedulerProvider.ui())
 .subscribe((Order order) -> {
    order.setAmountDue(amountDue);
    mOrderRepository.updateOrder(order);
});

但是,在可以从另一个来源合法地多次更新订单的情况下,这可能不是您想要的逻辑。在这种情况下,比较接收到的订单的amountDue(或其他相关属性)是否不同于更新金额可能是有意义的。如果是这样,请更新订单。

mOrderRepository.getOrder(orderId)
 .subscribeOn(mSchedulerProvider.io())
 .observeOn(mSchedulerProvider.ui())
 .subscribe((Order order) -> {
    // assuming `amountDue` has already been defined
    if (!order.getAmoundDue().equals(amountDue)) {
      order.setAmountDue(amountDue);
      mOrderRepository.updateOrder(order);
    }
});