USECASE: 我必须更新存储在本地数据库中的当前订单。步骤是:
我的第一个解决方案有点容易。只需调用后端,为每个项目创建两个数据库查询。首先检查它是否已经存在,然后再添加或更新它。
你可能想象它很慢。每次更新大约需要17.5秒。
第二个解决方案:将数据库数据缓存到列表中,而不是每次在ArrayList中搜索时查询数据库。这导致更新时间降至16.5秒。我使用defer
从数据库调用创建了Observable
,并使用combineLatest
来获取结果。
当前解决方案: 瓶颈当然是数据更新。我正在使用的orm库启用批量更新。所以我必须创建两个列表: DataToUpdate 和 DataToInsert 。
目前的解决方案在约5.3秒内运行。我对时间感到满意,但对这种非反应方式感到不满意。
Observable<List<OrderDto>> getAllOrdersObservable = backendService.getAllOrders();
ordersDisposable = Observable.combineLatest(getStoredOrder(), getAllOrdersObservable, this::insertOrUpdateOrders)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete(() -> {
Log.d(TAG, "Duration: " + (System.currentTimeMillis() - start) + " ms");
showSyncButton();
notifyListenersDataDownloaded();
})
.subscribe();
private Observable<List<Order>> getStoredOrder() {
return Observable.defer(() -> {
Log.d(TAG, "Started loading orders from database");
Observable<List<Order>> just = Observable.just(orderDao.loadAll());
Log.d(TAG, "Ended loading orders from database");
return just;
});
}
private List<Order> insertOrUpdateOrders(List<Order> orders, List<OrderDto> orderDtos) {
List<Order> ordersToInsert = new LinkedList<>();
List<Order> ordersToUpdate = new LinkedList<>();
for (OrderDto orderDto : orderDtos) {
Order order = getOrderByOrderNumber(orders, orderDto.getNumber());
if (order != null) {
dtoToEntityTransformer.updateFields(orderDto, order);
ordersToUpdate.add(order);
} else {
order = dtoToEntityTransformer.transformToEntity(orderDto);
ordersToInsert.add(order);
}
}
orderDao.insertInTx(ordersToInsert);
orderDao.updateInTx(ordersToUpdate);
return orders;
}
问题
您是否知道如何以反应方式解决这个问题?是否有一个运算符允许将两个列表中的observable分开。或者也许我应该使用一个全局变量(似乎是一个坏主意)来保留要插入的数据和要更新的数据?
答案 0 :(得分:1)
使用@Override
public void start(Stage primaryStage) {
Label label = new Label("Hello World!");
label.setTextFill(Color.WHITE);
Pane content = new Pane(label);
content.setPrefSize(2000, 2000);
content.setBackground(new Background(new BackgroundFill(
new LinearGradient(0, 0, 1, 1, true, CycleMethod.NO_CYCLE, new Stop(0, Color.RED), new Stop(1, Color.BLUE)),
CornerRadii.EMPTY,
Insets.EMPTY)));
ScrollPane scrollPane = new ScrollPane(content);
double targetX = 10;
double targetY = 10;
InvalidationListener listener = o -> {
Bounds viewportBounds = scrollPane.getViewportBounds();
Bounds contentBounds = content.getBoundsInLocal();
Bounds labelBounds = label.getBoundsInLocal();
double factorX = Math.max(contentBounds.getWidth() - viewportBounds.getWidth(), 0);
double factorY = Math.max(contentBounds.getHeight() - viewportBounds.getHeight(), 0);
label.setTranslateX(targetX + scrollPane.getHvalue() * factorX - labelBounds.getMinX());
label.setTranslateY(targetY + scrollPane.getVvalue() * factorY - labelBounds.getMinY());
};
scrollPane.viewportBoundsProperty().addListener(listener);
scrollPane.hvalueProperty().addListener(listener);
scrollPane.vvalueProperty().addListener(listener);
label.boundsInLocalProperty().addListener(listener);
Scene scene = new Scene(scrollPane, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
listener.invalidated(null);
}
,其中关键是它是否是更新/插入操作;你会得到一个包含密钥的GroupedObservable。使用该键执行适当的操作。