2014-11-10 2 views
7

Sono nuovo di RXJava e ho difficoltà a capire come concatenare il risultato delle chiamate API.Combinazione di chiamate API con RX Java

Sto effettuando due chiamate API utilizzando Retrofit, A e B, che restituiscono entrambi un elenco di oggetti osservabile. Entrambe le chiamate API sono indipendenti, quindi voglio fare entrambe le cose contemporaneamente, ma per raggiungere il mio risultato finale, devo prima prendere il risultato di A, fare un po 'di lavoro, quindi combinarlo con il risultato di B per popolare la mia lista di schede .

  • Fare API chiamata Una
  • Costruttore API Chiamata B
  • Prendere il risultato di A e creare risultato X
  • Prendere Risultato di B + X e popolare adattatore

    @GET("/{object_id}/object_a") 
        Observable<List<Object_A>> getObjectAList(
         @Path("object_id") long object_id); 
    
    
    @GET("/{object_id}/object_b") 
        Observable<List<Object_B>> getObjectBList(
         @Path("object_id") long object_id); 
    

Questo è dove mi perdo cercando di usare RX Java. Posso prendere il risultato della chiamata API A e fare il mio lavoro ma non sono sicuro come prendere il risultato che ho appena generato e combinarlo con API chiamata B.

aService. getObjectAList(object_a.getID()) 
      .subscribeOn(AndroidSchedulers.mainThread()) 
      .observeOn(AndroidSchedulers.main) 
      .subscribe(new Action1<List<Object_A>>() { 

       @Override 
       public void call(List<Section> sections) { 
        // Do Stuff Here... 
        // Now i need to take this result and combine it with API Call B... 
       } 
      }); 

Voglio fare entrambe le chiamate API allo stesso tempo, ma non sono sicuro di come concatenare e combinare le chiamate API. Qualsiasi aiuto è riconoscente.

risposta

2

La domanda è: come combinare i risultati?

Creazione di un nuovo risultato da Elenco ed elenco? Combinare oggetti con oggetti B?

La risposta a questa domanda aiuta a trovare l'operatore giusto per il problema.

Un semplice esempio di risultati di combinazione può essere questo:

getObjectAList().zipWith(getObjectBList(), (aList, bList) -> // combine both list to build a new result)).subscribe() 

È possibile combinare elementi della lista anche con un altro operatore (combineLatest per esempio)

aObs = getObjectAList().flatMap(Observable::from); 

bObs = getObjectBList().flatMap(Observable::from); 
Observable.combineLatest(aObs, bObs, (a,b) -> // combine a object with b object).subscribe(); 

Per tutti questi esempi precedenti , le richieste saranno fatte in parallelo da retrofit.

10

Qualcosa di simile?

Observable 
     // make api call for A list and B list 
     .combineLatest(getObjectAList(), getObjectBList(), new Func2<List<Object_A>, List<Object_B>, Object>() { 
      @Override 
      public Object call(List<Object_A> o, List<Object_B> o2) { 
       // Do what you need to do in the background thread 
       List x = createX(o); 
       List y = createY(x, o2); 
       return y; 
      } 
     }) 
     .subscribeOn(Schedulers.io()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(new Observer<Object>() { 
      @Override 
      public void onCompleted() { 

      } 

      @Override 
      public void onError(Throwable e) { 

      } 

      @Override 
      public void onNext(Object y) { 
       // UI thread, do what you need e.g. renders the list 
       mAdapter.setList(y); 
      } 
     }); 

Prendersi cura di sostituire i tipi appropriati dovrebbe portare abbastanza vicino alla soluzione.

+0

questo è il blocco ad es. se 1 chiamata fallisce, si ferma lì; come faccio a effettuare chiamate non bloccanti in parallelo @IvanMorgillo? Non ho bisogno di combinare i risultati, voglio gestire i risultati in modo indipendente – ericn

+0

"Func2" non supporta in rxbinding: 2.0.0. Che schifo noi invece? –

+0

Credo che tu possa usare questo http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Observable.html#combineLatest(io.reactivex.functions.Function,%20int,%20io.reactivex.ObservableSource ...) RxJava2. –

0

probabilmente sarei fare qualcosa di simile alla seguente

Observable convertedObservable = getObjectAList 
      .map(object_as -> convertAToX(object_as)); 

Observable.combineLatest(convertedObservable, getObjectBList, (listx, listb) -> { 
     return listx.addAll(listb); 
    }).subscribeOn(AndroidSchedulers.mainThread()) 
     .observeOn(AndroidSchedulers.main) 
     .subscribe(r -> { 
      setAdapterWith(r); 
    }); 

Tenete a mente questo sta usando lambda al posto delle classi anonime, ma si dovrebbe ottenere il succo. La mappa è un ottimo modo per convertire un tipo di oggetto in un altro (risultati da A a Risultati di X). Quindi puoi decidere come funziona il metodo convertAToX per te.Quindi è possibile utilizzare combineLastest su AX e B convertiti per restituire l'elenco di R che aggiorna il tuo adattatore

Idealmente questo è tutto in un ViewModel di qualche tipo dove getObjectAList e getObjectBList mi possono prendere in giro con Mock osservabili e puoi testare tutta la logica facilmente :)