Intereting Posts
Каков самый простой способ рисовать текстуру с помощью OpenGL ES? Android Wifi Direct: предотвращение принятия пользователем при подключении к известному партнеру Андроид поиск: настройка макета предложения TextView полужирный через xml-файл? Фрагмент Android, возвращающийся без повторного воспроизведения / перезагрузки Фрагмент Как определить обратные вызовы в Android? Android: вызов super () в начале или конце onStart (), onStop (), onDestroy () в активности? API Android для Google Диска – проверьте, существует ли папка Как отправить SMS с помощью Delphi XE5 в Android EnterTransitionCoordinator вызывает NPE в Android 5.0 Как я могу определить, будет ли Android-телефон в тихом режиме программным Просмотреть содержимое файла apk Как отключить предупреждение eclipse в производном файле IMarketBillingService.java? Обнаружить кнопку «Назад», но не отклонять диалоговое окно Android Instant Run В первый раз требуется слишком много времени для запуска приложения после установки

Обработка пейджинга с помощью RxJava

Я использую Retrofit + RxJava в приложении для Android и задаю себе вопрос о том, как обрабатывать разбиение на страницы API на цепочку вызовов до тех пор, пока все данные не будут восстановлены. Что-то вроде этого:

Observable<ApiResponse> getResults(@Query("page") int page); 

Объект ApiResponse имеет простую структуру:

 class ApiResponse { int current; Integer next; List<ResponseObject> results; } 

API вернет следующее значение до последней страницы.

Есть ли хороший способ добиться этого? Пытался объединить некоторые flatMaps () , но не имел успеха.

Solutions Collecting From Web of "Обработка пейджинга с помощью RxJava"

Вы можете моделировать его рекурсивно:

 Observable<ApiResponse> getPageAndNext(int page) { return getResults(page) .concatMap(new Func1<ApiResponse, Observable<ApiResponse>>() { @Override public Observable<ApiResponse> call(ApiResponse response) { // Terminal case. if (response.next == null) { return Observable.just(response); } return Observable.just(response) .concatWith(getPageAndNext(response.next)); } }); } 

Затем, чтобы уничтожить его,

 getPageAndNext(0) .concatMap(new Func1<ApiResponse, Observable<ResponseObject>>() { @Override public Observable<ResponseObject> call(ApiResponse response) { return Observable.from(response.results); } }) .subscribe(new Action1<ResponseObject>() { /** Do something with it */ }); 

Это должно дать вам поток ResponseObject , который поступит по порядку, и, скорее всего, придет в куски размера страницы.

Я ответил на свое решение в аналогичной должности: https://stackoverflow.com/a/34378263/143733

Трюк или поправка к решению, предоставленному @Iopar, – это включение «триггера», наблюдаемого, которое может быть выбрано различными способами.

В опубликованном мной коде он выдается после обработки полной страницы элементов, однако это может произойти и на основе щелчка пользователем кнопки / прокрутки.

Иопар дал отличный пример.

Просто небольшое дополнение.
Если вы хотите получить все страницы в одном вызове onNext ().
Это может быть полезно, если вы хотите закрепить этот результат еще одним наблюдаемым.
Вы должны написать:

 private List<String> list = new LinkedList() { { add("a"); add("b"); add("c"); } }; int count = 1; public Observable<List<String>> getAllStrings(int c) { return Observable.just(list) .concatMap( strings -> { if (c == 3) { return Observable.just(list); } else { count += 1; return Observable.zip( Observable.just(list), getAllStrings(count), (strings1, strings2) -> { strings1.addAll(strings2); return strings1; } ); } } ); } 

Использование :

 getAllStrings(0) .subscribe(strings -> { Log.w(TAG, "call: " + strings); }); 

И вы получите:

 call: [a, b, c, a, b, c, a, b, c, a, b, c]