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

Переполнение стека при использовании Retrofit rxjava concatWith

Я хочу обрабатывать разбиение на страницы в Retrofit с помощью rxjava Observable. Я последовал совету другого question.

У меня есть более 100 страниц, которые нужно извлечь, но цепочка выходит из строя вокруг 20-й страницы и останавливает любую дополнительную подписку на наблюдаемую с помощью ниже регистрируемого logcat

04-04 04:12:11.766    2951-3012/com.example.app I/dalvikvm﹕ threadid=28: Qaru on call to Ljava/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater;.compareAndSet:ZLJJ
04-04 04:12:11.766    2951-3012/com.example.app I/dalvikvm﹕ method requires 56+20+32=108 bytes, fp is 0x94b52350 (80 left)
04-04 04:12:11.766    2951-3012/com.example.app I/dalvikvm﹕ expanding stack end (0x94b52300 to 0x94b52000)
04-04 04:12:11.766    2951-3012/com.example.app I/dalvikvm﹕ Shrank stack (to 0x94b52300, curFrame is 0x94b548dc)

Кто-нибудь знает, почему это может случиться?

Обновление: Я знаю, что это происходит из-за рекурсии, но есть ли более грациозный способ обработки разбиения на страницы с помощью модификации и rxjava?

4b9b3361

Ответ 1

Итак, учитывая, что я ответил на исходный вопрос, на который вы ссылались, я должен, вероятно, попытаться ответить и на этот случай.:)

Это еще одна действительная (и, возможно, более простая) альтернатива моему первоначальному ответу на поисковый вызов, теперь, когда я разработал еще несколько трюков Rx в своем арсенале.:) (Сделано в псевдокоде java8 лямбда-стиля):

Observable.range(Integer.MAX_VALUE)
    // Get each page in order.
    .concatMap(page -> getResults(page))
    // Take every result up to and including the one where the next page index is null.
    .takeUntil(result -> result.next == null)
    // Add each output to a list builder. I'm using Guava ImmutableList, but you could
    // just as easily use a regular ArrayList and avoid having to map afterwards. I just
    // personally prefer outputting an immutable data structure, and using the builder
    // is natural for this.
    //
    // Also, if you wanted to have the observable stream the full output at each page,
    // you could use collect instead of reduce. Note it has a slightly different syntax. 
    .reduce(
        ImmutableList.<ResponseObject>builder(),
        (builder, response) -> builder.addAll(response.results))
    // Convert list builder to one List<ResponseObject> of all the things.
    .map(builder -> builder.build())
    .subscribe(results -> { /* Do something with results. */ });