Результаты конкатенации репозитория в RXKotlin - PullRequest
1 голос
/ 14 апреля 2020

Пытаясь прийти с первым приложением в автономном режиме, мне удалось создать рабочий шаблон репозитория, который сначала проверяет кэш, затем базу данных и, наконец, API. Я делаю это так:

private fun cachedTopics(): Maybe<List<Topic>> { ... }
private fun databaseTopics(): Maybe<List<Topic>> { ... }
private fun apiTopics(): Maybe<List<Topic>> { ... }

Maybe.concat(cachedTopics(), databaseTopics(), apiTopics())
     .firstOrError()
     .subscribeOn(scheduler)

Теперь дело в том, что я сохраняю частичные данные в базе данных (не во всех темах). Если пользователь подключен к inte rnet и просматривает отображаемые данные, будут только данные в базе данных. Но это еще не весь контент, к которому должен обращаться пользователь (если он подключен к inte rnet). Я знаю, что это связано с вызовом .firstOrError().

Но мне интересно, есть ли способ объединить отдельные результаты базы данных + api (api может завершиться ошибкой и, следовательно, вернуть 0 результатов) и вернуть Single.

Редактировать

Чтобы быть более понятным, я хочу что-то вроде следующего:

IF CACHE IS NOT EMPTY
   RETURN DISTINCT(DB + CACHE)
ELSE
   UPDATE CACHE WITH API RESULT
   RETURN DISTINCT(DB + API)

Где вызовы API автоматически приведут к тому, что ни результатов если не получится.

1 Ответ

1 голос
/ 14 апреля 2020

Возможно, вы хотите здесь: Maybe#switchIfEmpty (документы здесь )

Тогда вы можете сделать что-то вроде этого:

class Repository() {

    fun topics() {
        return cachedTopics.switchIfEmpty(databaseOrApiTopics());
    }


    private fun databaseOrApiTopics() = databaseTopics().switchIfEmpty(apiTopicsWithUpdate())

    private fun apiTopicsWithUpdate() = apiTopics().doOnComplete {
        // update db
        // update cache?
    }
}

ОБНОВЛЕНИЕ: если вы хотите чтобы объединить результаты вместе, вы можете сделать это с перегрузкой Maybe.flatMap, которая требует объединителя. Что-то вроде:

cachedTopics().switchIfEmpty(
    databaseTopics().flatMap { dbTopics ->
        apiTopics().doOnComplete { /* updateDb(it) */ }
            .map { apiTopics -> apiTopics + dbTopics }
    }
)
...