2015-05-14 6 views
10

ich Retrofit bin mit und ich fühle mich wie rxjava (mit retrolambda) wäre eine gute Passform für den folgenden Fluss sein:Verwenden RxJava und Nachrüstung durch die Liste zu durchlaufen und die Ergebnisse erweitern basierend auf Subqueries

  1. get Liste Widgets (http)
  2. für jedes Widget

    a) eine Liste der Artikel (http) für den gegebene Widget Typen
    b) erhalten speichert all
    c) den ersten (letzten) Artikel db in Liste und update wi dget.articleName und widget.articleUrl mit den entsprechenden Werten aus diesem Artikel

  3. Transformation zurück zur Liste und vollständige

jedoch unsicher Ich bin, was nach dem Schritt 2a zu tun. Hier ist mein Code so weit

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

ich gespielt habe, um mit einigen Betreibern aber als Verkettungs, ich scheine immer zu verengen zu weit (zB einen Griff an einem einzigen Artikel erhalten) und dann nicht mehr Zugang zu Das Original-Widget , um Änderungen vorzunehmen.

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

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

Antwort

19

Sie könnten doOnNext an bestimmten Punkten des Stroms einzufügen Nebenwirkungen hinzuzufügen:

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 runnable Beispiel.

+0

Brilliant hinzugefügt haben! Danke, dass Sie sich die Zeit genommen haben, eine so umfassende Antwort zu geben. Mein Wissen von RxJava hat gerade eine weitere Kerbe :) – Damian

+0

Sehr nette Antwort! –

+0

Große Antwort ... –

1

hier hinzufügen, da ich kein Beispiel finden konnte, eine Liste zu wiederholen, die in einem Objekt als Variable zurückgegeben wird.

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

akarnokds Antwort ist ziemlich hilfreich, aber das kann NetworkOnMainThreadException verursachen. zu lösen, dass ich

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

auf alle Anfragen

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) 
);