Banner

Wednesday, November 18, 2015

RxJava Operators - toList()

If you read my earlier post Understanding Observables, you already know that I like to think of Observable operations as stick figures passing boxes. The analogy made sense to me and it seemed to help others too. As I get more efficient at cheap animation, I'll see if I can cover other operators with these "RxMovers". I even have some ideas to visualize subscribeOn() and observeOn() with these guys.

The toList() operation reveals quite a bit about Observable behavior and how onNext() and onCompleted() calls can be manipulated. In my previous article that covered map(), the onNext() calls happen in sequence down the entire chain and get passed all the way to the final Subscriber.

The toList() operator intercepts onNext() calls. Rather than handing the items further down the chain, it catches them instead and adds them to a List (specifically an ArrayList). Only when the source Observable calls onCompleted() will it emit the entire List up the chain, then it will call onCompleted() up the chain.


The toList() in Action




The scene starts by Mover 1 taking boxes out of storage and pushing them to Mover 2, who represents the toList() operation. Instead of passing the boxes immediately to Mover 3, he instead collects them onto a dolly and does not pass anything to Mover 3. When Mover 1 has passed all items from the storage unit (which is three items), he calls onCompleted() on Mover 2 and says they are done.

However, Mover 2 does not pass the onCompleted() call to Mover 3 yet. This is his cue to push the dolly of items to Mover 3. He calls Mover 3's onNext() method and passes the entire List<Box> of items to him. Then Mover 2 calls onCompleted() which signals Mover 3 to close the truck.

This is how it may look in RxJava.

Observable<Box> mover1 = Observable.create(s -> {
 while (house.hasItems()) {
  s.onNext(house.getItem());
 }
 s.onCompleted();
});

Observable<List<Box>> mover2 = mover1.toList();

Subscription mover3 = mover2.subscribe(listOfBoxes -> 
    putInTruck(listOfBoxes));


The importance of onCompleted()

As you can probably guess, the onCompleted() call is very important with an operation like toList(). Logically, you cannot collect infinite emissions from an infinite Observable into a List, because a List is a finite collection of items. Therefore, if an onCompleted() call is never passed to a toList() operation, you will get some very undesired behaviors. These behaviors can range from infinite blocking because toList() infinitely keeps waiting for items, or it gives up and does not emit anything at all.

A few other operators are dependent on the onCompleted() call, such as last() and count(). So always be mindful and ensure the sequences are finite. Let me know if you have any questions.

Be sure to read my latest RxMover post on flatMap().

9 comments:

  1. Very good metaphor. I like the idea of animation! It is a very good tool, however, how much time did it take for you to create this animation?

    ReplyDelete
    Replies
    1. Glad you like it! With the learning curve with GIMP and Inkscape it took me about 90 minutes. But now that I understand layers, sprite, and scene reusability better, I think I can compose a scene in about 15-20 minutes. I plan on making more : )

      Delete
    2. GIMP made composing GIFs surprisingly doable. The tricky part for me was understanding and leveraging layers to maximize re-usability. But here was a helpful simple tutorial I used https://www.youtube.com/watch?v=f-9_HwRcd1A

      Delete
  2. You and your cool animations are doing this magic, I never understand RxJava this clear with this short explanation. Thank you :)

    ReplyDelete
  3. I am glad you are finding them helpful :)

    ReplyDelete
  4. very nice ,cool and easy explanation of RxJava concepts i ever come across. Thank you , Thomas. Waiting for your articles on other RxJava concepts

    ReplyDelete
    Replies
    1. Thank you! More articles will come. For now I'm writing an open book "Learning RxJava with JavaFX", as well as prepping for an O'Reilly webinar. But I've got some future article ideas that I will jot down soon...

      Delete