У меня есть докладчик, который вызывает метод getShops ().

Observable<List<Shop>> observable = interactor.getData();
        Subscription subscription = observable
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<List<Shop>>() {
                    @Override
                    public void onCompleted() {
                        view.hideProgress();
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                        view.hideProgress();
                    }

                    @Override
                    public void onNext(List<Shop> shops) {
                        handleShops(shops);
                        view.onSuccess();
                    }
                });
        composite.add(subscription);

На уровне данных у меня есть Interactor, который делает запрос к серверу с помощью Retrofit и возвращает List<Shop>.

@Override
public Observable<List<Shop>> getData() {
    return api.getShops(pageNum).map(new Func1<ShopWrapper, List<Shop>>() {
        @Override
        public List<Shop> call(ShopWrapper wrapper) {
            return wrapper.getShops();
        }
    });
}

Проблема в том, что мне нужно сделать несколько одинаковых запросов с разными параметрами страницы, потому что сервер возвращает N магазинов на страницу, и мне нужно собрать все магазины, а затем вернуть Observable<List<Shop>> ведущему.

Я новичок в реактивном программировании, возможно, есть оператор, который позволяет это сделать.

Любая помощь была бы признательна.

0
Jarik Eng 25 Ноя 2016 в 18:00

2 ответа

Лучший ответ

Просто используйте Observable.range и concatMap для своих звонков. Если вы не знаете свой верхний диапазон, вы можете использовать takeUntil с некоторым условием.

Что-то вроде этого:

Observable.range(0, Integer.MAX_VALUE)
            .concatMap(pageNum -> api.getShops(pageNum).map(doYourMapping))
            .takeUntil(shops -> someCondition);

Если вам нужен только один вызов onNext, вы можете добавить это после takeUntil:

.flatMapIterable(shops -> shops)
.toList();
2
Alexander Perfilyev 25 Ноя 2016 в 17:50

Вы можете добиться этого с помощью метода Observable.concat.

/**
 * Returns an Observable that emits the items emitted by two Observables, one after the other, without
 * interleaving them.
*/

Observable<List<Shop>> observable = Observable.concat(
            interactor.getData(0),  interactor.getData(1), interactor.getData(2) //and so on);

Ваш метод getData должен принимать параметр pageNum:
public Observable<List<Shop>> getData(int pageNum)

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

Вы можете попытаться решить эту с помощью рекурсивного построения наблюдаемого.

0
Community 23 Май 2017 в 12:32