Home » Android » Can I fetch the list of items and based on id get unique list and have in one Flowable both lists?

Can I fetch the list of items and based on id get unique list and have in one Flowable both lists?

Posted by: admin November 1, 2017 Leave a comment

Questions:

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

Answers:

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