Usecase: Мне нужно обновить текущие заказы, хранящиеся в локальной базе данных. Шаги:RxJava: Разделить на два списка
- Загрузка данных из внутреннего интерфейса (~ 800 наименований)
- Проверить, если локальная база данных уже содержит элемент. Бэкэнд-парни используют строку в качестве первичного ключа.
- Если товара нет в базе данных, добавьте его.
- Если элемент находится в базе данных, обновите его.
Моим первым решением было своеобразно легко. Просто вызовите бэкэнд и создайте два запроса к базе данных для каждого элемента. Сначала проверьте, есть ли он там, во-вторых, чтобы добавить или обновить его.
Как вы можете себе представить, это было медленно. Около 17,5 сек для каждого обновления.
Второе решение: Кэш данных базы данных в список и вместо запроса базы данных при каждом поиске в ArrayList. Это привело к сокращению времени обновления до 16,5 секунд. Я использовал defer
для создания Observable
из вызова базы данных и combineLatest
для получения результатов.
Текущее решение: Узкое место было, конечно же, обновлением данных. Библиотека ормы, которую я использую, включает пакетные обновления. Поэтому мне нужно создать два списка: 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;
}
Вопрос
Есть ли у вас представление о том, как решить эту проблему в реактивном способе? Есть ли оператор, который позволяет разделить наблюдаемые в двух списках. Или, может быть, я должен использовать глобальную переменную (похоже, плохую идею), чтобы сохранить информацию, которую данные вставлять и какие обновления?