Mark Elston (109) [Avatar] Offline
#1
I had trouble following the initial Observable example (page 48 - version 1). I had to go to the RXJava docs to find out, for example, that Observable.OnSubscribe<Integer> is an interface with a single abstract method, call. Once I saw that I could trace through this example and figure out (mostly) what you were doing.

While in the docs I notice that Observable has a constructor, Observable(Observable.OnSubscribe<T> f). Why couldn't you have just called that constructor instead of calling the create method?

I don't know what version of Java you are using but Java is a pretty wordy language with lots of noise in the code. Java 8 overcomes some of this with its use of lambdas and Functional Interfaces (Single Abstract Method interfaces). That might have helped here (if the OnSubscribe interface is annotated with @FunctionalInterface) but it might also have confused some readers who have not been exposed to it yet.

For me, though, a better step-by-step overview of even this simple code would have helped to figure out what is going on without googling the docs.

For example, what role does Observable.create actually play here? How does the implementation of Observable.OnSubscribe<Integer> fit into the scheme of things here (how is it used by Observer)? You introduce the create method without describing what it is doing with its parameter. Is it just passed directly to the constructor? Is something else happening?

Also, in the Observer portion of this example, you have Subscription speedSubscription = ... with no context. I have to assume this return value is held on to by something else otherwise the code would 'run off the end' of the function (or program) and return, get garbage collected and none of the output would come out.

Typically Manning books often annotate listing with #A, #B, #C, etc. to give additional information after the listing. That might be helpful here.
Sasa Sekulic (2) [Avatar] Offline
#2
We tried to keep things light, so the second chapter is there more to whet your appetite - and it seemed to have worked very well. smilie

We explain the differences in Observable creation methods in Chapter 4, where we discuss the merits of Observable.just, Observable.defer and Observable.create. I have intentionally steered away from lambdas in the examples in Chapter 4 exactly for the reason you mentioned - not to obscure the OnSubscribe.call() so that the readers will be able to see it.

As to why not simply use the constructor - there are some very specific reasons for that. For example, using Observable.just() and other methods (except Observable.create()) gives you built-in mechanisms to ensure your Observable creation adheres to the Observable contract (sends events in series, sends onCompleted when finished, checks to see whether the Observer unsubscribed, deals with backpressure etc.). You don't get any of those using Observable.create() which is the basic building block internally (at least in RxJava), and using the constructor directly you also lose the ability to use schedulers i.e. to move the OnSubscribe.call() execution to another thread.

To illustrate, here's the RxJava code from Observable.class:
protected Observable(OnSubscribe<T> f) {
        this.onSubscribe = f;
    }

static final RxJavaObservableExecutionHook hook = RxJavaPlugins.getInstance().getObservableExecutionHook();

public static <T> Observable<T> create(OnSubscribe<T> f) {
        return new Observable<T>(hook.onCreate(f));
}


You can see the difference - Observable.create() hooks into the executor, while the constructor doesn't. In fact, the comment in the code for the constructor explicitly says to not use it unless you need inheritance.

Subscriptions are also explained in Chapter 3 - they keep the relationship reference between the Observer and the Observable. so you use them to control the lifecycle (in general, to be able to release the resources when no longer needed) but also to prevent making new Subscriptions in case there's an already existing one in case you don't want to interrupt something that's under way.

For example, if you were to execute a network call, you would keep a Subscription in a member variable, then when the network call is finished it would send onCompleted to unsubscribe the Observer and hence clear the Subscription. That way, by checking Subscription.isUnsubscribed() you would be able to prevent executing another call while the first one is still being executed.

That, combined with some types of Subject that keep the values, enables you to optimize the network calls and implement simply memory caching, or to implement the default states - explained in more detail in Chapter 3.

BTW, thanks for asking all this - we should probably add a warning to never use the Observable constructor somewhere in the book.
Mark Elston (109) [Avatar] Offline
#3
Ok. Thanks. Can't wait for the next chapter(s).
448571 (2) [Avatar] Offline
#4
Hope you have satisfied with the reply from him. I have also faced the same problem. Now i am happy with the reply got for your post. I am managing a ayurveda retreat and people feeling great on our services.