Observable#take(Long) не возвращает желаемый размер элементов в RxJava

Я использую RxJava/Kotlin Observable#take() для получения первых 50 элементов из списка. Но оператор #take() ведет себя не так, как должен, согласно документам Rx.

В документах Rx #take() определяется как:

«Испускать только первые n элементов, испускаемых Observable»

введите здесь описание изображения

У меня есть такая функция:

Как мы видим, аргумент pageSize равен 50.

введите здесь описание изображения

И начальная size из list равна 300

введите здесь описание изображения

После этого #take(50) применяется к этому Observable, и в следующей контрольной точке я все еще получаю полный размер список i.e. size = 300

введите здесь описание изображения

Но just for the check, если что-то не так с отладчиком или наблюдаемым, я пытался брать только элементы, чье displayName содержит "9", но на этот раз я получаю ожидаемый результат smaller list с 9 в каждом из их #displayName field.

введите здесь описание изображения

Я считаю, что оператор RxJava/Kotlin's #take() не такой уж сумасшедший, и это просто я.


person erluxman    schedule 17.11.2018    source источник
comment
Я не уверен, но я думаю, что вы путаете две разные вещи здесь оператор Observable.take() считает выбросы наблюдаемого, а не размер испускаемого списка. Поэтому, если ваш remoteFollowersService.getFollowers() выдаст более 50 элементов, он вернет только первые 50 из них.   -  person iluu    schedule 17.11.2018


Ответы (2)


take ведет себя правильно, так как даст вам только 50 List<FollowersEntry> "марблов". Судя по вашим скриншотам и формулировкам, вы хотели 50 FollowersEntry. Существует фундаментальное логическое различие между контейнером объектов и самими объектами. RxJava видит только последовательность объектов типа List<>, но не может знать о вложенных объектах, с которыми вы намеревались работать.

Поэтому вам нужно либо использовать it.take(50) внутри map (или что там у Kotlin collections function), либо развернуть последовательность списков в последовательность записей через flatMapIterable:

getFollowers()
.flatMapIterable(entry -> entry)
.take(50 /* entries this time, not lists */)
person akarnokd    schedule 17.11.2018
comment
Я пытался заснуть, и то же самое пришло мне в голову, я открыл ноутбук и получил этот ответ, потрясающе .. спасибо :) Разум всегда находит решение после того, как пытается задать хороший вопрос .. - person erluxman; 17.11.2018

Внимательно посмотрите на возвращаемый тип вашего метода — Single<List<FollowersEntity>>. Observable, возвращаемый из remoteFollowersService.getFollowers(), не Observable, который генерирует 300 FollowersEntity элементов, а Observable, который генерирует один > элемент, и этот единственный элемент представляет собой List, содержащий 300 FollowersEntity элементов. Другими словами, вам нужно вызывать take по списку, а не по наблюдаемому.

    return remoteFollowersService.getFollowers()
        .map { val size = it.size; it } // for debugging
        .map { it.take(pageSize) }
        .map { val size = it.size; it } // for debugging
        .map { it.filter { item -> item.displayName.contains("9") } }
        .single(emptyList())
person Leo Aso    schedule 17.11.2018