Подтвердить что ты не робот

Сетевые запросы RxJava и кэширование

Я ищу пример потока, который я пытаюсь реализовать с помощью RxJava.

Предположим, что я хочу показать список данных. Поток должен выглядеть примерно так:

  • Прочитать кеш. Если он содержит данные, покажите его:
  • Отправьте запрос API на сервер:

    Если он вернет данные, затем кешируйте их и покажите.

    Если оно вернулось и ошибка и не было кэшированных данных, тогда покажите ошибку.

    Если он вернулся и ошибка, и что-то было кешировано, тогда ничего не делайте.

Сейчас у меня есть метод который делает что-то подобное (с большим вдохновением от Jake u2020), Основное различие заключается в том, что он использует кэширование в памяти, что означает, что нет необходимости в отдельном Observable для чтения из кеша, и это можно сделать синхронно.

Я не знаю, как объединить два наблюдаемых (один для чтения из кеша, а другой для вызова API) и получить описанный выше поток.

Любые предложения?

4b9b3361

Ответ 1

Вот мое решение:

readDataFromCache().defaultIfEmpty(null)
        .flatMap(new Func1<Data, Observable<Data>>() {

            @Override
            public Observable<Data> call(final Data data) {
                if (data == null) {
                    // no cache, show the data from network or throw an error
                    return apiCall();
                } else {
                    return Observable.concat(
                            Observable.just(data),
                            // something cached, show the data from network or do nothing.
                            apiCall().onErrorResumeNext(Observable.<Data>empty()));
                }
            }
        });

Я не добавляю subscribeOn и observeOn, потому что я не уверен, что readDataFromCache() должен использовать ioScheduler или uiScheduler.

Ответ 2

Думаю, я решил свою проблему. Наблюдаемая цепочка выглядит так:

apiCall()
        .map(data -> dataInMemory = data)
        .onErrorResumeNext(t -> data == null ?
                Observable.just(Data.empty()) : Observable.empty())
        .startWith(readDataFromCache().map(data -> dataInMemory = data))
        .subscribeOn(ioScheduler)
        .observeOn(uiScheduler)
        .subscribe(dataRequest);

Главное, что если readDataFromCache() выдает сообщение об ошибке, он вызывает onCompleted() без вызова onError(). Таким образом, это должен быть пользовательский Observable, который вы можете контролировать.

Data.empty() является заглушкой для моих данных - Subscriber следует рассматривать как ошибку.

dataInMemory является членом моего контроллера, который действует как кеш в памяти.


EDIT: решение не работает должным образом. Завершение одного варианта использования (см. Комментарий) не достигается.

EDIT 2: хорошо, решение работает правильно после некоторой настройки. Исправление возвращало различные типы наблюдаемых в зависимости от состояния кэша в памяти. Вид грязный.