防止多个表更改时 Room Observable 查询多次触发

Prevent Room Observable Query Triggering Multiple Times When Multiple Tables Changed

我在 Android Room 中使用可观察查询来触发更新,这些更新最终会在基础数据发生变化时更改 UI。

有时这些查询涉及多个表,有时用户执行将新值插入这些表的操作。插入通常一个接一个地快速完成(即不到二分之一秒的时间跨度)

目前,从 Room 订阅更新的观察者将被触发 x 次,其中 x 是查询中已更新的表数。

因此,如果在一秒内将值插入到查询中的六个不同表中,则任何正在观察查询的观察者都会触发六次。

有没有办法告诉Room; "Only trigger observers a maximum of once every second"?或者,更好的是 "When you see an update, wait half a second to collect any other updates, and then notify observers of everything at once"?

这里是房间查询。如您所见,涉及多个表。

 @Query("SELECT Distinct order_material.* FROM order_material" +
            " JOIN orders on order_material.orderId = orders.id" +
            " JOIN assignment on order_material.id = assignment.orderMaterialID" +
            " JOIN box_inside on assignment.boxInsideID = box_inside.id" +
            " WHERE orders.isActive = 1 " +
            " AND (box_inside.dateCFOrigPacked <= :dateLimitYema OR box_inside.stemLength IS NOT NULL)" +
            " AND assignment.id IN (SELECT id FROM assignment WHERE active = 1" +
            "      AND quantity > 0 AND assignment.id NOT IN "+
            "              (Select assignmentID FROM " +
            "               (Select assignmentID, assignment.quantity as sum_assign, SUM(preparation.quantityPrepared) as sum_prep " +
            "               from preparation "  +
            "               JOIN assignment on preparation.assignmentID = assignment.id"  +
            "               GROUP BY preparation.assignmentID " +
            "               HAVING sum_assign <= sum_prep)))" +
            " Order By order_material.deliveryDate ASC")
    Observable<OrderMaterial[]> getOrderMaterialsReadyToPrepareAsync(Date dateLimitYema);

这是一个观察查询的存储库方法。它被触发 X 次,其中 X 是在很短的时间内更新的表的数量。

 public Observable<List<OrderMaterial>> findOrderMaterialsReadyToPrepareAsync(){
        int daysInOneWeek = 7;
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1 * daysInOneWeek);
        Date limitOneWeekYemas = calendar.getTime();

        return Observable.create(subscribe ->
            assignmentDao.getOrderMaterialsReadyToPrepareAsync(limitOneWeekYemas)
                    .observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io())
                    .subscribe(new Observer<OrderMaterial[]>() {
                        @Override
                        public void onSubscribe(Disposable d) {
                            Timber.v("findOrderMaterialsReadyToPrepareAsync on subscribe");
                            subscribe.setDisposable(d);
                            preparationDisposable.add(d);
                        }

                        @Override
                        public void onNext(OrderMaterial[] materials) {
//                            Timber.v("findOrderMaterialsReadyToPrepareAsync onNext with %s", Arrays.toString(materials));
                            subscribe.onNext(Arrays.asList(materials));
                        }

                        @Override
                        public void onError(Throwable e) {
                            Timber.e(e,"findOrderMaterialsReadyToPrepareAsync onError");
                            subscribe.onError(e);
                        }

                        @Override
                        public void onComplete() {
                            Timber.e("findOrderMaterialsReadyToPrepareAsync onComplete");
                        }
                    })
        );
    }

Is there a way to tell Room; "Only trigger observers a maximum of once every second"? Or, better yet "When you see an update, wait half a second to collect any other updates, and then notify observers of everything at once"?

据我所知,目前还没有这种与 Room 通信的方式。 Room 中的可观察查询(使用 LiveData、RxJava、Flow)在后台调用使用 DB's InvalidationTracker(就像一个简单的任何更改触发器):

Adds the given observer to the observers list and it will be notified if any table it observes changes.

不仅如此,即使您观察(使用 Observables 之一)具有某些条件(例如 select * from users where id =:id)的查询,您也会在每次 table 的更改后收到通知,即使有具有此特定 ID 的 table 行没有变化。

您可以尝试将 @Transaction 添加到您的查询中(只触发一次),但我想这无济于事。

所以我认为你不应该期望 Room 在这方面有太多智能。然后 RxJava 如果你使用它 - 是你期待如此智能的第一个候选 "conversation" (可能 debounce 运算符将是你的选择)。