3
votes

New to RxJava and I have question about interface callbacks ( called from inner layer/module of code through interface variable) vs RxJava. To make it more clear, quick example:

Standard callback interface implementation, interface, class A and B

interface CustomCallback {
    void onCallbackCalled(String str);
}
class ClassA {
    private ClassB classB;
    public ClassA() {
        classB = new ClassB(new CustomCallback() {
            @Override
            public void onCallbackCalled(String str) {
                System.out.println("Callback called " + str);
            }
        });
    }
}
class ClassB {
    private CustomCallback customCallback;
    public ClassB(CustomCallback callback) {
        customCallback = callback;
    }
    private void somethingHappened() {
        customCallback.onCallbackCalled("method somethingHappened");
    }
}

When classB method "somethingHappened" is called, result is: "Callback called method somethingHappened". Interface's method onCallbackCalled(String str) can be called from classB as many times as I want.

CLASS A ↓ ............................................ injection of interface through constructor

CLASS B................↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ onCallbackCalled(...) 0...n number

Now RxJava. 99% of cases which I find.

class ClassA {
    private ClassB classB;
    public ClassA() {
        classB = new ClassB();
    }

    public void rxJavaMethod() {
                DisposableObserver<String> observer = classB.getObservable()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableObserver<String>() {

                    @Override
                    public void onNext(String s) {}

                    @Override
                    public void onError(Throwable e) {}

                    @Override
                    public void onComplete() {}
                });
    }
}

class ClassB {
    private Observable<String> getObservable() {
        return Observable.just(can be different from "just", for sake of example);
    }
}

Scheme is:

CLASS A ↓........................ one call for getting Observable resource

CLASS B................↑ EDIT returns observable which emits 0...n values

So basically you call from top layer ( in this example) and you get response about state from inner layer.

QUESTIONS:

1) What in case when you have a model ( inner layer) which is changing dynamically ( but not any kind of AsyncTask etc.), and you want to notify top layer ( UI for example) that state has changed ( good example: game).

2) Is there any kind of "bridge" class in RxJava library ( I think about it as "subscribe to it, then you can pass arguments to it as many times as you want and information/observable will be emitted to subscribers).

3) Is there any sense and advanatage of trying to do that instead of standard interface callbacks ( in case like above, not " click button, get response once")

UPDATE, ANSWER BASED ON EXAMPLE ABOVE

As Bob Dalgleish mentioned, way of making such bridge is by using one of the class extending Subject<T> rxjava. http://reactivex.io/documentation/subject.html

class ClassA {
    private ClassB classB;
    public ClassA() {
        classB = new ClassB();
    }

    public void rxJavaMethod() {
                DisposableObserver<String> observer = classB.getCallbackSubjectRx()
                .subscribeWith(new DisposableObserver<String>() {

                    @Override
                    public void onNext(String s) {}

                    @Override
                    public void onError(Throwable e) {}

                    @Override
                    public void onComplete() {}
                });
    }
}

class ClassB {
    private BehaviorSubject<String> mCallbackRx;
    public ClassB() {
        mCallbackRx = BehaviorSubject.create();
    }

    // method somethingHappened can be invoked whenever whe want and
    // it will send given parameter to all subscribers
    private void somethingHappened() {
        mCallbackRx.onNext("method somethingHappened");
    }

    // multiple subscribers allowed
    public BehaviorSubject<String> getCallbackSubjectRx() {
        return mCallbackRx;
    }
}

Downside might be, that if we want to use one "bridge" to handle multiple callback types ( interface have methods, we use only one method: "onNext()"), we might need to create wrapper class with callback parameters. Which isn't big problem in my opinion.

On the other hand, we get access to all of RxJava operators. http://reactivex.io/documentation/operators.html

( Example above is for RxJava2, where Disposable is basically Subscription from RxJava1).

1
You will need to read the RxJava documentation. There are also many tutorials on the internet. Did you need help finding a good tutorial? - Bob Dalgleish
No, I don't. Thanks. I'm not sure if you're mocking or not, but question is legit. I wouldn't ask here if I could find this by simply typing "how to callback RxJava" ;). I found a solution to a "problem" ( still not sure if it's worth of doing so), and aboved can be achived with use of BehaviorSubject<> class from RxJava library ( object which is Observable and Observer at the same time). I'll update and add answer to question in spare time. Cheers. - Gregory Iwanek
I wasn't really sure what you were asking. I will try to answer below. And no, I was not mocking. - Bob Dalgleish
This question is a little hard for me to understand. I suppose it's because I don't know enough of the RxJava, I just know of interface callbacks - Harsha

1 Answers

0
votes

The first thing to note is that

CLASS B................↑ returns 0...n observables to observer

is not true. Class B returns an observable, on which it will occasionally emit 0..n values.

  1. (the question is not clear). The inner observable, from class B, is changing state for whatever reason. The most common reason is that another process/task/thread is feeding it, and you want to display the resulting state in the UI.

  2. A simple type of "bridging" class that I use all the time any of the several Subject<> classes. You can emit new values to them using .onNext() and the subscribers will get those values.

  3. If callback interfaces were all standardized, then they would have some advantage, but they vary all over the place. You have to remember that you need some particular interface for this thing you are looking at and and a different one for the other thing. While UI events tend to be quite uniform these days, trying to mix UI events and network events and database events will still leave you feeling overwhelmed. Having a much smaller class of interfaces, mostly encapsulated inside of the rxJava generic classes, makes composing functionality much easier.

Edit: Improve example code.

There is a good article from Yammer Engineering on using Observable.create() (formerly Observable.fromEmitter(), formerly Observable.fromAsync(). The important points he makes are

  1. Using Observable.create() handles the subscription step for you by registering a listener to the underlying interface. More importantly, it arranges to de-register the listener when the unsubscribe() occurs.

  2. Out of the box, this code handles multiple subscribers, each of which receives its own observable stream of data.

  3. As I mentioned above, the listener protocol is particular to the thing you register with. If that thing supports only a single listener, then you will likely want to introduce a Subject that subscribes to the thing under observation, and all your other observers subscribe to the subject.

End of edit.

My favorite example of composition of solutions is the distinctUntilChanged() operator. Because it is an operator that works on a generic observable, it encapsulates the stateful property of saving consecutive values for comparison and only emitting differing ones. I use it frequently for logging state changes. To achieve the same end using standard callback interfaces would require adding a different interface for saving prior values to every existing interface.

So, yes, most of the time it is worth using the rxJava approach of observables, simply for the sake of not having to remember which of the many call back protocols might be applicable in the current case.