Комната с Rx Java - объединить запрос списка с данными каждого элемента - PullRequest
0 голосов
/ 15 января 2020

У меня есть приложение Android, которое использует Room и Rx Java.

Допустим, у меня есть две таблицы box(id) и ball(id, color, boxId). Мне нужен запрос, который возвращает все поля с количеством шаров каждого цвета.

Flowable<List<BoxWithBallsCount>> getBallsWithCount();

Имея это:

BoxWithBallsCount(Box box, BoxCount boxCount)
BoxCount(String ballColor, int count)

Я создаю следующий Дао

@Dao
public interface BoxDao {
    @Query("SELECT * FROM box")
    Flowable<List<Box>> getAll();

    @Query("SELECT ball.color, count(*) FROM box WHERE ball.boxId = :boxId GROUP BY ball.color")
    Flowable<List<BoxCount>> dificultQuery(String herdId);
}

Теперь мне нужно реализовать основной метод: flowable, который returns список BoxWithBallsCount. Как мне это сделать?

Я перепробовал много подходов RX, но не могу найти правильный путь.

Спасибо

1 Ответ

0 голосов
/ 23 января 2020

Я создал вспомогательную функцию для достижения результата:

https://gist.github.com/mateuyabar/7f125de87788432e351d2066d94503d9#file -rxfunctions- java

package com.mateuyabar.rx;


import java.util.ArrayList;
import java.util.List;
import io.reactivex.Flowable;



/**
 * Extended RX functions
 * @author mateuyabar.com
 */
public class RxFunctions {
    /**
     * For each item on the list published by the publisher, it will map it using the mapper, and will use the merger to create the merged result.
     * @return Publisher list of merged items
     */
    static public <T, U, V> Flowable<List<V>> flatMapForEach(Flowable<List<T>> listPublisher, ItemMapper<T, U> mapper, Merger<T,U,V> merger){
        return listPublisher.flatMap(listItem -> addData(listItem, mapper, merger));
    }

    static private <T, U, V> Flowable<List<V>> addData(List<T> listItem, ItemMapper<T,U> mapper, Merger<T,U,V> merger) {
        if(listItem.isEmpty())
            return Flowable.just(new ArrayList<>());

        List<Flowable<V>> result = new ArrayList<>();
        for(T item : listItem){
            result.add(
                    mapper.subQuery(item)
                            .map(subQueryResult -> merger.merger(item, subQueryResult))
            );
        }
        return Flowable.combineLatest(result, objects -> asList(objects));
    }

    static private <T> List<T> asList(Object[] objects) {
        List<T> reuslt = new ArrayList<>();
        for(Object object:objects){
            reuslt.add((T) object);
        }
        return reuslt;
    }

    public interface ItemMapper<T, U>{
        Flowable<U> subQuery(T item);
    }

    public interface Merger<T, U, V>{
        V merger(T item, U subquery);
    }
}
...