2015-05-14 13 views
10

sto usando retrofit e mi sento come rxjava (con retrolambda) sarebbe una buona misura per il seguente flusso:Usa RxJava e retrofit per scorrere la lista e aumentare i risultati basati sul sottointerrogazioni

  1. lista dei get widgets (http)
  2. per ciascun widget

    a) ottenere un elenco di articoli (http) per il dato tipo di widget di
    b) salvare tutti coloro che a DB
    c) prendere la prima (ultimo articolo) in lista e aggiornamento wi dget.articleName e widget.articleUrl con i valori appropriati da questo articolo

  3. trasformano torna alla lista e completo

Tuttavia io sono sicuro che cosa fare dopo la fase 2 bis. Ecco il mio codice finora

apiService.getWidgets(token) 
    .flatMapIterable(widgets -> widgets) 
    .flatMap(widget -> apiService.getArticles(token, widget.type)) 
    ... 
    .toList() 
    .subscribe(
    modifiedWidgets -> saveWidgets(modifiedWidgets), 
    throwable -> processWidgetError(throwable) 
); 

Ho giocato in giro con alcuni operatori, ma quando il concatenamento, mi sembra sempre di restringere troppo (ad esempio, ottenere una maniglia su un singolo articolo) e quindi non hanno più accesso ai il widget originale per apportare modifiche.

@GET("/widgets") 
Observable<List<Widget>> getWidgets(@Header("Authorization") String token); 

@GET("/articles") 
Observable<List<Article>> getArticles(@Header("Authorization") String token, @Query("type") String type); 

risposta

19

Si potrebbe inserire doOnNext in determinati punti del torrente per aggiungere effetti collaterali:

apiService.getWidgets(token) 
.flatMapIterable(v -> v) 
.flatMap(w -> 
    apiService.getArticles(token, w.type) 
    .flatMapIterable(a -> a) 
    .doOnNext(a -> db.insert(a)) 
    .doOnNext(a -> { 
     w.articleName = a.name; 
     w.articleUrl = a.url; 
    }) 
    .takeLast(1) 
    .map(a -> w) 
) 
.toList() 
.subscribe(
    modifiedWidgets -> saveWidgets(modifiedWidgets), 
    throwable -> processWidgetError(throwable) 
); 

Here is esempio eseguibile di questo.

+0

Brilliant! Grazie per aver dedicato del tempo a fornire una risposta così completa. La mia conoscenza di RxJava ha appena aumentato un'altra tacca :) – Damian

+0

Risposta molto bella! –

+0

Ottima risposta ... –

1

aggiungendo questo qui poiché non sono riuscito a trovare un esempio di iterazione di un elenco restituito in un oggetto come variabile.

getUserAccount(token) 
    .subscribeOn(Schedulers.newThread()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .flatMap(userResponse -> Observable.just(userResponse.list))  //get list from response 
    .flatMapIterable(baseDatas -> baseDatas)       //make the list iterable 
    .flatMap(baseData ->            //on each project, get the details 
      getProjectDetails(baseData.name,token) 
        .subscribeOn(Schedulers.io())      //get network call off the main thread 
        .observeOn(AndroidSchedulers.mainThread())) 
    .subscribe(
      (dataResponse) -> { 
       Timber.d("Got Data Details:" + dataResponse); 
      }, 
      (error) -> { 
       Timber.e("Got Error:" + error.getMessage()); 
      }, 
      () -> { 
       Timber.d("Completed Data Details"); 
      } 
    ); 
0

La risposta di akarnokd è molto utile ma potrebbe causare NetworkOnMainThreadException. Per risolvere questo ho aggiunto

.observeOn(AndroidSchedulers.mainThread()) 
.subscribeOn(Schedulers.io()) 

su ogni richiesta

apiService.getWidgets(token) 
.observeOn(AndroidSchedulers.mainThread())  //added this 
.subscribeOn(Schedulers.io())     //added this 
.flatMapIterable(v -> v) 
.flatMap(w -> 
    apiService.getArticles(token, w.type) 
    .observeOn(AndroidSchedulers.mainThread()) //added this 
    .subscribeOn(Schedulers.io())    //added this 
    .flatMapIterable(a -> a) 
    .doOnNext(a -> db.insert(a)) 
    .doOnNext(a -> { 
     w.articleName = a.name; 
     w.articleUrl = a.url; 
    }) 
    .takeLast(1) 
    .map(a -> w) 
) 
.toList() 
.subscribe(
    modifiedWidgets -> saveWidgets(modifiedWidgets), 
    throwable -> processWidgetError(throwable) 
);