使用 Retrofit rxjava concatWith 时发生堆栈溢出
Stack overflow when using Retrofit rxjava concatWith
我想使用 rxjava Observable 在 Retrofit 中处理分页。我听从了另一个 的建议。
我有超过 100 个页面需要获取,但链在第 20 页左右失败并停止对 logcat
中以下日志的可观察对象的任何进一步订阅
04-04 04:12:11.766 2951-3012/com.example.app I/dalvikvm﹕ threadid=28: stack overflow 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)
有人知道为什么会这样吗?
更新:我知道这是由于递归而发生的,但是有没有更优雅的方法来处理 retrofit 和 rxjava 的分页?
因此,鉴于我回答了您提到的原始问题,我可能也应该尝试回答这个案例。 :)
这是我原来的分页答案的另一个有效(并且可能更简单)替代方案,现在我已经在我的武器库中开发了一些 Rx 技巧。 :)(在 java8 lambda 风格的伪代码中完成):
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's 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. */ });
我想使用 rxjava Observable 在 Retrofit 中处理分页。我听从了另一个
我有超过 100 个页面需要获取,但链在第 20 页左右失败并停止对 logcat
中以下日志的可观察对象的任何进一步订阅04-04 04:12:11.766 2951-3012/com.example.app I/dalvikvm﹕ threadid=28: stack overflow 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)
有人知道为什么会这样吗?
更新:我知道这是由于递归而发生的,但是有没有更优雅的方法来处理 retrofit 和 rxjava 的分页?
因此,鉴于我回答了您提到的原始问题,我可能也应该尝试回答这个案例。 :)
这是我原来的分页答案的另一个有效(并且可能更简单)替代方案,现在我已经在我的武器库中开发了一些 Rx 技巧。 :)(在 java8 lambda 风格的伪代码中完成):
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's 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. */ });