2015-04-04 7 views
14

Ich möchte Seitenumbruch in Retrofit mit Rxjava Observable behandeln. Ich folgte dem Rat von einem anderen question.Stapelüberlauf bei Verwendung von Retrofit rxjava concatWith

Ich habe mehr als 100 Seiten, die geholt werden muss, aber Kette nicht um die 20. Seite und stoppt jede weitere Abonnement der beobachtbaren mit dem unten Protokoll im 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) 

Weiß jemand, warum diese das könnte passieren?

Update: Ich weiß, dass dies aufgrund von Rekursion passiert, aber gibt es eine elegantere Art der Seitenumbruch mit Retrofit und Rxjava?

Antwort

23

Also, wenn ich die ursprüngliche Frage, auf die Sie verwiesen haben, beantwortet habe, sollte ich wahrscheinlich versuchen, auch diesen Fall zu beantworten. :)

Dies ist eine andere gültige (und möglicherweise einfachere) Alternative zu meiner ursprünglichen Paging-Antwort, jetzt, da ich ein paar mehr Rx Tricks in meinem Arsenal entwickelt habe. :) (Fertig in java8 Lambda-Stil Pseudo-Code):

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. */ }); 
+0

bekamen schließlich um zu diesem ... Habe mit einem ähnlichen Ansatz kommt und hatte es :) – Bhuvan

+3

Super Code arbeiten! Ich nehme an, dass "Observable.range" auch "int start" braucht! –

+0

Sagen wir, ich habe 1000 Seiten, ist es machbar/Gut? – Ajinkya