2017-08-18 1 views
0

vereinfachen Ich mag würde wissen, wie mit RxJava2 etwa wie folgt auszuführen,Wie könnte ich dies mehrere abhängige Anrufe mit RxJava2

  • einen API-Aufruf machen eine Liste von Elementen zu erhalten
  • iterieren die Liste der Elemente
    • , wenn der Artikel ist spezifischer Typ
      • einen API-Aufruf machen Benutzerdaten erhalten
      • einen API-Aufruf machen Sie eine Liste von Daten mit dem Element-ID & Benutzernamen zu erhalten (von Details)
      • Iterierte über die Liste der Daten
        • , wenn das Datenelement Code den Einzelteilcode (von äußeren Schleife) übereinstimmt
          • Update das Element in der äußeren Liste durch Kopieren von Daten Element, um es
  • Rückkehr der Liste

Am ziemlich neu in RxJava und versuchte, dies für den ersten API-Aufruf mit einem Single tun und dann mit dem map Operator und in der Mapper-Funktion dann tat nur dem Rest der Sachen mit einer normalen äußeren und inneren Schleife.

Ich würde wirklich gerne wissen, ob der Mapper-Funktionsteil auch irgendwie einfacher mit RxJava erledigt werden könnte als mit den verschachtelten Loops?

+0

Bitte geben Sie Ihr Modell Klassen –

Antwort

0

Ihre äußere Schleife könnte wie folgt aussehen:

Observable.fromIterable(list) 
    .flatMap(item -> checkItemAndReplace(item)) 
    .toList(); 

und die innere Schleife sein könnte:

Observable<ItemType> checkItemAndReplace(ItemType item) { 
    if (isItemOfSpecificType(item)) { 
    return getUpdatesForItem(item); 
    } 
    return Observable.just(item); 
} 

und so weiter für die innere Schleife. Ich habe die Dinge in verschachtelte Funktionsaufrufe aufgeteilt, die Observables zurückgeben, aber Sie können sie in eine beobachtbare Kette zusammenfügen, abhängig von Ihrem Code-Stil und den Testanforderungen.

Die Punkte zu beachten:

  1. Sie vom und zum normalen Datenstrukturen mit verschiedenen Observablenoperatoren umwandeln kann. fromIterable() und just() konvertieren zu Observablen, während toList() zurück in eine Liste konvertiert wird.
  2. Verwenden Sie map(), wenn die Operation von einem Wert in einen anderen oder einen nicht beobachtbaren Wert in einen anderen konvertiert; Verwenden Sie flatMap(), wenn Sie ein Observable in die von ihm erzeugten Werte konvertieren müssen.
+0

Dank wird geben, dass ein Versuch und Post zurück. Übrigens, weißt du, ob es auch bei der Verwendung einer 'Single' gleich wäre? – Bootstrapper

+0

Das Problem mit 'Single' anstelle von' Observable' für 'checkItemAndReplace()' ist, dass Sie es für den 'flatMap()' Operator in 'Observable' umwandeln müssen. Wenn 'getUpdatesForItem()' '' Single' 'zurückgibt, dann würden Sie es in der return-Anweisung in 'Observable' umwandeln. –

0

Werfen Sie einen Blick auf die Api-Schnittstelle und die itemsToBeRefreshed beobachtbar sind. Sie können Observable verwenden.fromIterable, um über eine Liste zu iterieren und flatMap verschiedene API-Aufrufe zu ketten. Wenn Sie ein Anfrage-Antwort-Verhalten haben, sollten Sie Single als Rückgabetyp verwenden. Außerdem sollten Sie die Eigenschaften von Elementen im Stream nicht ändern. Kopieren Sie einfach die zu ändernden Objekte in ein neues Objekt und schreiben Sie sie zurück.

@Test 
public void name() throws Exception { 
    Api api = mock(Api.class); 

    when(api.getItems()).thenReturn(Single.just(Arrays.asList(
      new Item(0, 123), 
      new Item(1, 123), 
      new Item(2, 333) 
    ))); 

    when(api.getUserDetails(eq(0))).thenReturn(Single.just(new UserDetails("hans wurst", 0))); 
    when(api.getUserDetails(eq(1))).thenReturn(Single.just(new UserDetails("mett wurst", 1))); 
    when(api.getUserDetails(eq(2))).thenReturn(Single.just(new UserDetails("kaese wurst", 2))); 

    when(api.getData(eq(0), eq("hans wurst"))).thenReturn(Single.just(new Data(123))); 
    when(api.getData(eq(1), eq("mett wurst"))).thenReturn(Single.just(new Data(123))); 
    when(api.getData(eq(2), eq("kaese wurst"))).thenReturn(Single.just(new Data(666))); 

    Observable<Item> itemsToBeRefreshed = api.getItems() 
      .flatMapObservable(strings -> Observable.fromIterable(strings)) 
      .filter(s -> s instanceof Item) // test for specific type 
      .flatMapMaybe(item -> api.getUserDetails(item.id) 
        .flatMap(userDetails -> api.getData(userDetails.id, userDetails.userName)) 
        .filter(data -> data.code == item.code) 
        .map(data -> new Item(-1, -1)) // create new Item and copy properties over from data 
      ); 

    itemsToBeRefreshed.test() 
      .assertValueCount(2); 

    // subscribe to 'itemsToBeRefreshed' in order to write back items or just chain it to itemsToBeRefreshed with doOnNext 
} 

interface Api { 
    Single<List<Item>> getItems(); 

    Single<UserDetails> getUserDetails(int id); 

    Single<Data> getData(int id, String userName); 
} 

class Item { 
    int id; 

    int code; 

    Item(int id, int code) { 
     this.id = id; 
     this.code = code; 
    } 
} 

class UserDetails { 
    String userName; 
    int id; 

    UserDetails(String userName, int id) { 
     this.userName = userName; 
     this.id = id; 
    } 
} 

class Data { 
    int code; 

    Data(int code) { 
     this.code = code; 
    } 
}