Выборка Single <List>для всех элементов другого Single <List>в RxKotlin - PullRequest
0 голосов
/ 21 октября 2019

A, B, C являются объектами

Все вызовы функций выполняются в БД Rooms

Этот фрагмент кода находится внутри ViewModel

repo = Repository

Итак, я делаю приложение для Android (не могу предоставить подробности), и для определенного экрана мне нужно сделать следующее.

Мой первый вызов - repo.getInfo, который возвращает Single Observable ListOfA: Single<List<A>> // выполнить некоторые операции

для каждого элемента ListOfA Мне нужно вызвать другую функцию repo.getB (A), которая возвращает Single Observable ListOfB: Single<List<B>> // выполнить некоторые операции

для каждого элемента ListOfB мне нужно вызвать другую функцию repo.getC (B), которая возвращает Single Observable ListOfC: Single<List<C>> // выполнить некоторые операции

после того, как у меня есть необходимые данные, мне нужновызовите другую функцию, которая объединяет данные для отображения в пользовательском интерфейсе.

Теперь я не могу заставить это работать. Вот что я попробовал. Но поток останавливается на линии, помеченной THIS LINE, и переходит к блоку подписки. Индивидуальные вызовы функций работают, поэтому данные не являются проблемой. Я довольно новичок в этом и, честно говоря, не в своей тарелке. Любая помощь или подсказка приветствуется. Спасибо

localListOfA = emptyList<A>()
localListOfB = emptyList<B>()
localListOfC = emptyList<C>()
compositeDisposable.add(
    getInfo.map{listOfA ->
        localListOfA.addAll(listofA)
        listOfA.map {elementA ->   ////THIS LINE
            getB(elementA.id).map{listOfB ->
                listOfB.filter {
                    //some logic to select a few objects
                }
            }.map { it // filtered list of B
                localListofB.addAll(it)
                localListOfB.last() //I only need the top element of this list
            }.map{elementB ->
                getC(elementB.id).map{ listOfC ->
                    localListOfC.addAll(listOfC)
                    //do some operations
                }
            }
        }
    }
    .subscribeOn(DEFAULT_CACHED_SCHEDULERS)
    .observeOn(AndroidSchedulers.mainThread())
    .doOnError(/*take log*/)
    .subscribe{
        prepareUi()
    }
)

1 Ответ

1 голос
/ 21 октября 2019

Вы можете преобразовать List в Observable, используя .flattenAsObservable

getInfo // Single<List<A>>
    .doOnSuccess { localListOfA.addAll(it) } // Side effect, adding to localListOfA
    .flattenAsObservable { it } // Observable<A>
    .flatMapSingle { elementA -> getB(elementA.id) } // Observable<List<B>>
    .map { it.filter { true } } // Some logic to select a few objects from B
    .doOnNext { localListOfB.addAll(it) } // Side effect, adding to localListOfB
    .map { it.last() } // Observable<B>, only the last element
    .flatMapSingle { elementB -> getC(elementB.id) } // Observable<List<C>>
    .doOnNext { localListOfC.addAll(it) } // Side effect, adding to localListOfC
    .flatMapIterable { it } // Observable<C>

Теперь вы упомянули, что вам нужно как-то объединить эти данные. В Rx вы можете вкладывать цепочки, чтобы получить доступ к промежуточным данным. Например, если у вас есть вызов, который возвращает Single<Foo>, и вам требуется Foo для функции getBar(foo: Foo): Single<Bar>, один из способов достижения этого заключается в следующем:

getFoo().flatMap { foo -> // .concatMap, .switchMap
    getBar(foo).map { bar ->
        // Use both foo and bar
    }
}
...