Observable#take(Long) not returning desired size of items in RxJava

625 Views Asked by At

I am using RxJava/Kotlin Observable#take() to get first 50 items from the list. But #take() operator is not behaving as it should as per Rx docs.

In Rx docs, #take() is defined as:

"Emit only the first n items emitted by an Observable"

enter image description here

I have a function like this:

As we can see the pageSize argument is 50

enter image description here

And initial size of the list is 300

enter image description here

After that #take(50) is applied to that Observable and at next breakpoint I still get the full size list i.e. size = 300

enter image description here

But just for the check, if something is wrong with the debugger or observable, I tried to take only items whose displayName contains "9", but this time I get the expected result of smaller list with 9 in each of their #displayName field.

enter image description here

I believe RxJava/Kotlin's #take() operator is not that crazy and it's just me.

2

There are 2 best solutions below

1
On BEST ANSWER

take behaves correctly as it will give you only 50 List<FollowersEntry> "marbles". Based on your screenshots and wording, I guess you wanted 50 FollowersEntry. There is a fundamental logical difference between a container of objects and the objects themselves. RxJava sees only an object sequence of type List<> but it can't know about the nested objects you intended to work with.

Therefore, you either have to use it.take(50) inside map (or whatever the Kotlin collections function is) or unroll the sequence of lists into sequence of entries via flatMapIterable:

getFollowers()
.flatMapIterable(entry -> entry)
.take(50 /* entries this time, not lists */)
0
On

Take a good look at the return type of your method - Single<List<FollowersEntity>>. The Observable returned from remoteFollowersService.getFollowers() is not an Observable that emits 300 FollowersEntity items - it is an Observable that emits a single item, and that single item is a List containing 300 FollowersEntity items. In other words you need to call take on the list, not on the observable.

    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())