RxJava объединяет данные из сети и базы данных - PullRequest
0 голосов
/ 17 октября 2019

Это очень популярный вопрос, на который могут быть разные ответы,
, но я изо всех сил пытаюсь решить его правильным способом.

Чего я хочу достичь:

  • В случае отсутствия ошибок сначала выведите кэшированные данные из базы данных, а затем обновите их данными из сети, как только они будут получены.
  • В случае ошибки на пульте, показать данные из базы данных, , но также понять, что произошла ошибка и отображаются «кэшированные результаты» (этопроблема в моем случае)

Во-первых, у меня есть 2 метода в хранилище, которые возвращают соответственно данные из сети и базы данных:

private fun getUsersFromRemote(): Single<List<User>>() =
    remote.getUsers()
        .flatMap {
            // saving fetched data to database
            db.userDao().insert(MakeDbMapper.mapFrom(it))
                .andThen(Single.just(it))
        }

private fun getUsersFromDatabase(): Flowable<List<User>>() =
    db.userDao.getUsers()
        .distincUntilChanged()

(пропустите здесь сопоставление сущностей для простоты))

И открытый метод выглядит так:

fun getUsers(): Flowable<List<User>> =
        Flowable.mergeDelayError(
            getUsersFromRemote()
                .toFlowable(),
            geUsersFromDb()
                .filter { it.isNotEmpty() })
            .distinctUntilChanged()
  • В такой реализации onError не вызывается из-за того, что mergeDelayError ожидает завершения всех потоков. Очевидно, что поток базы данных не собирается делать это.
  • В случае использования Flowable.merge() Кажется, он работает как нужно -> сначала я получаю данные из базы данных, а затем ошибку. Однако, похоже, что это не правильный путь, потому что возможно получить ошибку из удаленного источника данных, а не из базы данных. Это приведет к прекращению потока перед получением кэшированных данных.
  • Возможно, имеет смысл сделать 2 открытых метода в хранилище,

, таких как:

fun subscribeForUsers(): Flowable<List<User>> = db.usersDao.getUsers()

и

fun refreshUsersFromRemote(): Completable = 
    remote.getUsers()
        .flatMapCompletable {
            db.userDao().insert(it)
        }

В таком сценарии refreshUsersFromRemote() позволит мне обработать удаленную ошибку, а также поможет опубликовать обновленных пользователей в subscribeForUsers() после добавления новых элементов в базу данных. .

Последний подход, кажется, работает для меня, но я не уверен, что он правильный.
В таком случае мне придется вызывать 2 метода из уровня Presentation, однако я бы хотелвызовите только один и инкапсулируйте всю логику объединения источников данных в репозитории.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...