2016-04-22 14 views
13

Ich habe 2 APIs, die ich nacheinander anfordern und ihre Daten in SQLite speichern möchte.Verkettungsanfragen in Retrofit + RxJava

Zuerst möchte ich eine Anfrage an die API A stellen und ihre Daten in der SQL-Tabelle a speichern. Dann stellen Sie eine Anfrage an die API B und speichern Sie ihre Daten in der Tabelle b und einige Daten in der Tabelle a_b. Die in a_b gespeicherten Daten stammen von der Anfrage B allein.

Wie kann ich dies mit RxJava tun. Ich habe irgendwo gelesen, über die Verwendung von flatMap dafür, so etwas wie diese

apiService.A() 
    // store in DB here? How? maybe use map()? 
    .flatMap(modelA -> { 
     // or maybe store modelA in DB here? 
     return apiService.B().map(modelB -> { 
      storeInDB()l // store B here ? 
      return modelB; 
     }); 
    }); 

Wenn ich nicht Lambda-Funktionen verwenden, dies als normale verschachtelte Anrufe als hässlich aussehen würde. Ist das ein besserer Weg?

Antwort

13

Ich glaube nicht, mit map Betreiber ist der beste Weg, Dinge zu gehen, wie das Ergebnis der api Aufruf zu speichern.

Was ich tun möchte, ist diese Dinge innerhalb doOnNext Betreiber zu trennen. So würde Ihr Beispiel so etwas wie dieses:

apiService.A() 
     .doOnNext(modelA -> db.store(modelA)) 
     .flatMap(modelA -> apiService.B()) 
     .doOnNext(modelB -> db.store(modelB)); 

(fügen notwendig observeOn und subscribeOn sich, genau wie Sie sie benötigen)

+0

Ich wusste nichts über 'do'-Operatoren von Rx. Ist 'doOnComplete' nach dem Lesen seiner Dokumente nicht eine bessere Funktion dafür? – Sourabh

+0

@Sourabh es hängt von Ihrem 'Observable' ab. Wenn 'onComplete' nach einem erfolgreichen Aufruf von api aufgerufen wird, dann ja. Wenn Ihr 'Observable' mehrere Ereignisse ausgeben kann, sollten Sie' doOnNext' wählen. In Ihrem Fall ('Retrofit') wird' doOnNext' und 'doOnComplete' das gleiche Ergebnis haben, aber' doOnComplete' ist vielleicht ein bisschen intuitiver (ich habe 'doOnNext' aus reiner Gewohnheit verwendet). –

+0

Ich meinte, benutzen 'doOnComplete' anstelle von' flatMap' – Sourabh

18

Ja, Sie können Flatmap für genau diesen Zweck verwenden. Siehe unten stehende Beispiel (Angenommen, Ihre Dienstleistung A kehrt Observable<FooA> und Service-B liefert Observable<FooB>)

api.serviceA() 
     .flatMap(new Func1<FooA, Observable<FooB>>() { 
      @Override 
      public Observable<FooB> call(FooA fooA) { 
       // code to save data from service A to db 

       // call service B 
       return api.serviceB(); 
      } 
     }) 
     .subscribeOn(Schedulers.io()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(new Subscriber<FooB>() { 
      @Override 
      public void onCompleted() { 
      } 

      @Override 
      public void onError(Throwable e) { 

      } 

      @Override 
      public void onNext(FooB fooB) { 
       // code to save data from service B to db 

      } 
     }); 
+0

Wenn ich Code schreiben, Daten an die DB in OnNext speichern Sie es auf Haupt-Thread ausgeführt wird Recht? So speichern Sie Daten in db im Hintergrund Thread statt? –

+0

werfen Sie einen anderen "flatMap" -Operator ein. 'api.serviceA(). flatMap ((FooA) -> {// Anrufdienst B}). flatMap ((FooB) -> {// Daten von Service B speichern und eine beobachtbare Nachricht mit Erfolg/Fehlschlag zurückgeben}). subscribeOn (Schedulers.io()). ObserveOn (AndroidSchedulers.mainThread()). DoOnNext ((isSuccess) -> {// Nur das wird am Hauptthread ausgeführt}} –

+0

Wie würden Sie das in RxJava2 tun? – Ryan

Verwandte Themen