Reputation: 2053
I fetch from DB list of ShoppingList Items each item has has recipeId ,for example if I have 10 shoppinglist items 8 of them can have the same recipeId and the rest of the shoppinglist items another recipeId.It means 10 items could represent 2 recipes. So I fetch 10 shoppinglist items ,then I have 10 recipeIds . I should keep unique recipeIds (in these case we have 2 recipeIds) and then get recipes for that recipeIds ,Note: I need to display 10 shoppinglist items and 2 recipes.
Can I fetch all these information in Flowable, or I need to subscribe to shoppingListItems and then in separate flowable based on this list have list of unique recipeIds
And if it possible which is the best solution
Upvotes: 0
Views: 485
Reputation: 4012
Lets say, you have shopping items and you want fetch for each unique recepId information:
Environment::
RxJava 2.0.7
assertJ 3.8.0
--
This code groups the recepIds (unique) and requests for each recepId the recep and joins the result back to the ShoppingItem.
@Test
void name() {
Observable<Tuple2<ShoppingListItem, Recep>> tuple = getFromDb().flatMapIterable(i -> i)
.groupBy(shoppingListItem -> shoppingListItem.recepId)
.flatMap(g -> {
Observable<Recep> recep = getRecep(g.getKey());
return Observable.combineLatest(recep, g, (recep1, shoppingListItem) -> {
return Tuple.of(shoppingListItem, recep1);
});
});
TestObserver<Tuple2<ShoppingListItem, Recep>> test = tuple.test()
.assertValueCount(4)
.assertComplete()
.assertNoErrors();
List<Tuple2<ShoppingListItem, Recep>> values = test.values();
assertThat(values).extracting("_1").extracting("recepId").contains(0, 1);
assertThat(values).extracting("_1").extracting("id").containsExactly(0, 1, 2, 3);
assertThat(values).extracting("_2").extracting("id").containsExactly(1, 1, 0, 0);
}
Observable<List<ShoppingListItem>> getFromDb() {
List<ShoppingListItem> shoppingListItems = Arrays.asList(
new ShoppingListItem(0, 1),
new ShoppingListItem(1, 1),
new ShoppingListItem(2, 0),
new ShoppingListItem(3, 0)
);
return Observable.just(shoppingListItems);
}
Observable<Recep> getRecep(int id) {
return Observable.just(new Recep(id));
}
class Recep {
private final int id;
public Recep(int id) {
this.id = id;
}
}
class ShoppingListItem {
private final int id;
private final int recepId;
public ShoppingListItem(int id, int recepId) {
this.id = id;
this.recepId = recepId;
}
}
Return List of ShoppingItems and List of Receps in grouped object:
@Test
void name() {
Observable<Items> itemsObservable = getFromDb().flatMapSingle(shoppingListItems -> {
List<Integer> collect = shoppingListItems.stream().map(i -> i.recepId)
.distinct()
.collect(Collectors.toList());
return Observable.fromIterable(collect).flatMap(this::getRecep)
.toList()
.zipWith(Single.just(collect), (receps, integers) -> {
return new Items(receps, shoppingListItems);
});
});
TestObserver<Items> test = itemsObservable.test()
.assertValueCount(1)
.assertComplete()
.assertNoErrors();
Items items = test.values().get(0);
assertThat(items.receps).hasSize(2);
assertThat(items.shoppingListItems).hasSize(4);
}
Observable<List<ShoppingListItem>> getFromDb() {
List<ShoppingListItem> shoppingListItems = Arrays.asList(
new ShoppingListItem(0, 1),
new ShoppingListItem(1, 1),
new ShoppingListItem(2, 0),
new ShoppingListItem(3, 0)
);
return Observable.just(shoppingListItems);
}
Observable<Recep> getRecep(int id) {
return Observable.just(new Recep(id));
}
class Items {
private final List<Recep> receps;
private final List<ShoppingListItem> shoppingListItems;
Items(List<Recep> receps, List<ShoppingListItem> shoppingListItems) {
this.receps = receps;
this.shoppingListItems = shoppingListItems;
}
}
class Recep {
private final int id;
public Recep(int id) {
this.id = id;
}
}
class ShoppingListItem {
private final int id;
private final int recepId;
public ShoppingListItem(int id, int recepId) {
this.id = id;
this.recepId = recepId;
}
}
Upvotes: 1