2016-04-22 21 views
13

Ho 2 API a cui desidero fare richiesta in sequenza e memorizzare i loro dati in SQLite.Richieste di concatenamento in Retrofit + RxJava

Prima di tutto desidero fare richiesta all'API A e memorizzarne i dati nella tabella SQL a. Quindi fai richiesta all'API B e memorizza i suoi dati nella tabella b e alcuni dati nella tabella a_b. I dati memorizzati in a_b provengono dalla richiesta B.

Come posso farlo utilizzando RxJava. Ho letto da qualche sull'utilizzo flatMap per questo, qualcosa di simile

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

Se non stavo usando funzioni lambda, questo apparirebbe brutto come chiamate annidate normali. È un modo migliore per farlo?

risposta

13

Non credo usando map operatore è il modo migliore per andare con le cose come memorizzare il risultato della chiamata API.

Quello che mi piace fare è separare queste cose dagli operatori doOnNext. Così il vostro esempio potrebbe essere qualcosa di simile:

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

(aggiungere necessaria observeOn e subscribeOn da soli, esattamente come ne avete bisogno)

+0

Non sapevo degli operatori 'do' di Rx. Dopo aver letto i suoi documenti, non è "doOnComplete" una funzione migliore per questo? – Sourabh

+0

@Sourabh dipende dal tuo 'Osservabile'. Se "onComplete' viene chiamato dopo una chiamata riuscita da api, allora sì. Se il tuo 'Observable' può emettere più eventi, allora dovresti usare' doOnNext'. Nel tuo caso ('Retrofit') usare' doOnNext' e 'doOnComplete' avranno lo stesso risultato, ma in effetti' doOnComplete' potrebbe essere un po 'più intuitivo (ho usato 'doOnNext' per pura abitudine). –

+0

Volevo dire, usare 'doOnComplete' invece di' flatMap' – Sourabh

18

Sì, è possibile utilizzare flatmap per questo scopo esatto. Vedere l'esempio di seguito (Assumendo che il servizio A torna Observable<FooA> e servizio B torna 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

Se scrivo il codice per salvare i dati di DB in onNext verrà eseguito sul thread principale destra? Come salvare i dati in db sul thread in background? –

+0

lanciare un altro operatore 'flatMap'. 'api.serviceA(). flatMap ((FooA) -> {// chiama il servizio B}). flatMap ((FooB) -> {// salva i dati dal servizio B e restituisce un errore/successo indicativo affermativo}). subscribeOn (Schedulers.io()). ObservOn (AndroidSchedulers.mainThread()). DoOnNext ((isSuccess) -> {// Solo questo verrà eseguito sul thread principale}) ' –

+0

Come lo faresti in RxJava2? – Ryan

Problemi correlati