2015-04-04 18 views
14

Desidero gestire l'impaginazione in Retrofit utilizzando rxjava Observable. Ho seguito il consiglio di un altro question.Overflow dello stack quando si utilizza Retrofit rxjava concatWith

ho più di 100 pagine che deve essere recuperato, ma la catena viene a mancare intorno alla pagina 20 e si ferma ogni ulteriore abbonamento al osservabile con il log di seguito nella 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) 

Qualcuno sa perché questo potrebbe succedere?

Aggiornamento: So che questo accade a causa della ricorsione, ma esiste un modo più aggraziato di gestire l'impaginazione con retrofit e rxjava?

risposta

23

Quindi, dato che ho risposto alla domanda originale a cui si è fatto riferimento, probabilmente dovrei provare a rispondere anche a questo caso. :)

Questa è un'altra alternativa valida (e potenzialmente più semplice) alla mia risposta di paginazione originale, ora che ho sviluppato alcuni trucchi Rx nel mio arsenale. :) (fatto in java8 lambda in stile pseudo):

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

finalmente ottenuto intorno a questo ... era venuto con un approccio simile e lo fece lavorare :) – Bhuvan

+3

codice Impressionante! Suppongo che anche 'Observable.range' abbia bisogno di' int start' anche! –

+0

Diciamo che sto avendo 1000 pagine è fattibile/Buono? – Ajinkya