我在Android Room中使用可观察的查询来触发更新,这些更新最终会在基础数据发生更改时更改UI。
有时这些查询涉及多个表,有时用户执行将新值插入这些表的操作。通常,插入操作非常快速地完成(即在不到一半的时间间隔内)]
[当前,从Room订阅更新的观察者将被触发x次,其中x是查询中已更新的表数。
因此,如果将值彼此之间在一秒钟内全部插入查询的六个不同表中,则观察该查询的任何观察者将触发六次。
是否有办法告诉Room; “仅触发观察者每秒最多一次”?或者,更好的方法是“当您看到更新时,请等待半秒钟以收集其他任何更新,然后立即将所有内容通知观察者”?
这里是会议室查询。如您所见,其中涉及多个表。
@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");
}
})
);
}
是否有办法告诉Room; “仅触发观察者每秒最多一次”?或者,更好的方法是“当您看到更新时,请等待半秒钟以收集其他任何更新,然后立即将所有内容通知观察者”?
据我所知,还没有与Room交流的方法。后台的Room中可观察到的查询(使用LiveData,RxJava,Flow)使用DB's InvalidationTracker调用(就像一个简单的任何更改触发器):
将给定的观察者添加到观察者列表中,如果它观察到的任何表发生更改,都将得到通知。
不仅如此,即使您以某种条件(例如select * from users where id =:id
)观察(使用Observables之一)查询,即使更改了该特定ID的表的行没有变化,也会在每张表更改后得到通知。
您可以尝试将@Transaction添加到查询中(仅触发一个),但我想这无济于事。
因此,我认为您不应该期望Room从这方面获得太多的情报。然后,如果您使用RxJava,则它是期望进行此类智能“对话”的第一个候选对象(可以选择debounce
运算符)。