防止多个表更改时 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
运算符将是你的选择)。
我在 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
运算符将是你的选择)。